brintos

brintos / linux-shallow public Read only

0
0
Text · 6.0 KiB · e5c625a Raw
220 lines · c
1// SPDX-License-Identifier: GPL-2.0+2 3#include <linux/iosys-map.h>4 5#include <drm/drm_atomic.h>6#include <drm/drm_atomic_helper.h>7#include <drm/drm_blend.h>8#include <drm/drm_fourcc.h>9#include <drm/drm_gem_atomic_helper.h>10#include <drm/drm_gem_framebuffer_helper.h>11 12#include "vkms_drv.h"13#include "vkms_formats.h"14 15static const u32 vkms_formats[] = {16	DRM_FORMAT_ARGB8888,17	DRM_FORMAT_XRGB8888,18	DRM_FORMAT_XRGB16161616,19	DRM_FORMAT_ARGB16161616,20	DRM_FORMAT_RGB56521};22 23static struct drm_plane_state *24vkms_plane_duplicate_state(struct drm_plane *plane)25{26	struct vkms_plane_state *vkms_state;27	struct vkms_frame_info *frame_info;28 29	vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL);30	if (!vkms_state)31		return NULL;32 33	frame_info = kzalloc(sizeof(*frame_info), GFP_KERNEL);34	if (!frame_info) {35		DRM_DEBUG_KMS("Couldn't allocate frame_info\n");36		kfree(vkms_state);37		return NULL;38	}39 40	vkms_state->frame_info = frame_info;41 42	__drm_gem_duplicate_shadow_plane_state(plane, &vkms_state->base);43 44	return &vkms_state->base.base;45}46 47static void vkms_plane_destroy_state(struct drm_plane *plane,48				     struct drm_plane_state *old_state)49{50	struct vkms_plane_state *vkms_state = to_vkms_plane_state(old_state);51	struct drm_crtc *crtc = vkms_state->base.base.crtc;52 53	if (crtc && vkms_state->frame_info->fb) {54		/* dropping the reference we acquired in55		 * vkms_primary_plane_update()56		 */57		if (drm_framebuffer_read_refcount(vkms_state->frame_info->fb))58			drm_framebuffer_put(vkms_state->frame_info->fb);59	}60 61	kfree(vkms_state->frame_info);62	vkms_state->frame_info = NULL;63 64	__drm_gem_destroy_shadow_plane_state(&vkms_state->base);65	kfree(vkms_state);66}67 68static void vkms_plane_reset(struct drm_plane *plane)69{70	struct vkms_plane_state *vkms_state;71 72	if (plane->state) {73		vkms_plane_destroy_state(plane, plane->state);74		plane->state = NULL; /* must be set to NULL here */75	}76 77	vkms_state = kzalloc(sizeof(*vkms_state), GFP_KERNEL);78	if (!vkms_state) {79		DRM_ERROR("Cannot allocate vkms_plane_state\n");80		return;81	}82 83	__drm_gem_reset_shadow_plane(plane, &vkms_state->base);84}85 86static const struct drm_plane_funcs vkms_plane_funcs = {87	.update_plane		= drm_atomic_helper_update_plane,88	.disable_plane		= drm_atomic_helper_disable_plane,89	.reset			= vkms_plane_reset,90	.atomic_duplicate_state = vkms_plane_duplicate_state,91	.atomic_destroy_state	= vkms_plane_destroy_state,92};93 94static void vkms_plane_atomic_update(struct drm_plane *plane,95				     struct drm_atomic_state *state)96{97	struct drm_plane_state *new_state = drm_atomic_get_new_plane_state(state,98									   plane);99	struct vkms_plane_state *vkms_plane_state;100	struct drm_shadow_plane_state *shadow_plane_state;101	struct drm_framebuffer *fb = new_state->fb;102	struct vkms_frame_info *frame_info;103	u32 fmt;104 105	if (!new_state->crtc || !fb)106		return;107 108	fmt = fb->format->format;109	vkms_plane_state = to_vkms_plane_state(new_state);110	shadow_plane_state = &vkms_plane_state->base;111 112	frame_info = vkms_plane_state->frame_info;113	memcpy(&frame_info->src, &new_state->src, sizeof(struct drm_rect));114	memcpy(&frame_info->dst, &new_state->dst, sizeof(struct drm_rect));115	memcpy(&frame_info->rotated, &new_state->dst, sizeof(struct drm_rect));116	frame_info->fb = fb;117	memcpy(&frame_info->map, &shadow_plane_state->data, sizeof(frame_info->map));118	drm_framebuffer_get(frame_info->fb);119	frame_info->rotation = drm_rotation_simplify(new_state->rotation, DRM_MODE_ROTATE_0 |120						     DRM_MODE_ROTATE_90 |121						     DRM_MODE_ROTATE_270 |122						     DRM_MODE_REFLECT_X |123						     DRM_MODE_REFLECT_Y);124 125	drm_rect_rotate(&frame_info->rotated, drm_rect_width(&frame_info->rotated),126			drm_rect_height(&frame_info->rotated), frame_info->rotation);127 128	frame_info->offset = fb->offsets[0];129	frame_info->pitch = fb->pitches[0];130	frame_info->cpp = fb->format->cpp[0];131	vkms_plane_state->pixel_read = get_pixel_conversion_function(fmt);132}133 134static int vkms_plane_atomic_check(struct drm_plane *plane,135				   struct drm_atomic_state *state)136{137	struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state,138										 plane);139	struct drm_crtc_state *crtc_state;140	int ret;141 142	if (!new_plane_state->fb || WARN_ON(!new_plane_state->crtc))143		return 0;144 145	crtc_state = drm_atomic_get_crtc_state(state,146					       new_plane_state->crtc);147	if (IS_ERR(crtc_state))148		return PTR_ERR(crtc_state);149 150	ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,151						  DRM_PLANE_NO_SCALING,152						  DRM_PLANE_NO_SCALING,153						  true, true);154	if (ret != 0)155		return ret;156 157	return 0;158}159 160static int vkms_prepare_fb(struct drm_plane *plane,161			   struct drm_plane_state *state)162{163	struct drm_shadow_plane_state *shadow_plane_state;164	struct drm_framebuffer *fb = state->fb;165	int ret;166 167	if (!fb)168		return 0;169 170	shadow_plane_state = to_drm_shadow_plane_state(state);171 172	ret = drm_gem_plane_helper_prepare_fb(plane, state);173	if (ret)174		return ret;175 176	return drm_gem_fb_vmap(fb, shadow_plane_state->map, shadow_plane_state->data);177}178 179static void vkms_cleanup_fb(struct drm_plane *plane,180			    struct drm_plane_state *state)181{182	struct drm_shadow_plane_state *shadow_plane_state;183	struct drm_framebuffer *fb = state->fb;184 185	if (!fb)186		return;187 188	shadow_plane_state = to_drm_shadow_plane_state(state);189 190	drm_gem_fb_vunmap(fb, shadow_plane_state->map);191}192 193static const struct drm_plane_helper_funcs vkms_plane_helper_funcs = {194	.atomic_update		= vkms_plane_atomic_update,195	.atomic_check		= vkms_plane_atomic_check,196	.prepare_fb		= vkms_prepare_fb,197	.cleanup_fb		= vkms_cleanup_fb,198};199 200struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev,201				   enum drm_plane_type type, int index)202{203	struct drm_device *dev = &vkmsdev->drm;204	struct vkms_plane *plane;205 206	plane = drmm_universal_plane_alloc(dev, struct vkms_plane, base, 1 << index,207					   &vkms_plane_funcs,208					   vkms_formats, ARRAY_SIZE(vkms_formats),209					   NULL, type, NULL);210	if (IS_ERR(plane))211		return plane;212 213	drm_plane_helper_add(&plane->base, &vkms_plane_helper_funcs);214 215	drm_plane_create_rotation_property(&plane->base, DRM_MODE_ROTATE_0,216					   DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK);217 218	return plane;219}220