From patchwork Mon Mar 4 15:28:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Louis Chauvet X-Patchwork-Id: 13580733 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A7CBAC54E4A for ; Mon, 4 Mar 2024 15:29:24 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 9FF3D10F955; Mon, 4 Mar 2024 15:29:23 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=bootlin.com header.i=@bootlin.com header.b="YvXwNrLG"; dkim-atps=neutral Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) by gabe.freedesktop.org (Postfix) with ESMTPS id CD11011227C for ; Mon, 4 Mar 2024 15:29:21 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id 88B1A1C000F; Mon, 4 Mar 2024 15:29:19 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1709566160; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hht86WDYBmmd5HJ0kBTByD9xXyq+2Qqfx093Hdq4g/E=; b=YvXwNrLGXkufDCSG+1XjivYgxRnZjO9WG5OVZyqWdr5kzrL5jzdzABr5ve8GgEIQ+hwzlj TVx0ma4pNURIECzev+kqR9bljSpKP/3KS7VL3GyaiwVi9oChl4Ys8uI7Lmj8SziVKRtYa8 f3owFq+RJU+6ZcrZji67FsRScvm2ciVN8CRpaiMs++ZXbDSKTMoFhZ1p3P9bhhyRtXV9FJ TMlK2d6L9dn+8Y/hkW62vDu7+gK3iuJyCOl1S6f5bJc3F3DBPuVgmDJvQgbqGnU94dBqtM f/HXL9T9OjN3iKNE9l85BB2WQfWUnZIqz4SDus3/kTK53e4N7kXUv8hJWz5qyw== From: Louis Chauvet Date: Mon, 04 Mar 2024 16:28:06 +0100 Subject: [PATCH v4 01/14] drm/vkms: Code formatting MIME-Version: 1.0 Message-Id: <20240304-yuv-v4-1-76beac8e9793@bootlin.com> References: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> In-Reply-To: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> To: Rodrigo Siqueira , Melissa Wen , =?utf-8?q?Ma=C3=ADra_Canal?= , Haneen Mohammed , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , arthurgrillo@riseup.net, Jonathan Corbet , pekka.paalanen@haloniitty.fi Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, jeremie.dautheribes@bootlin.com, miquel.raynal@bootlin.com, thomas.petazzoni@bootlin.com, seanpaul@google.com, marcheu@google.com, nicolejadeyee@google.com, Louis Chauvet X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=4834; i=louis.chauvet@bootlin.com; h=from:subject:message-id; bh=jQLWVvGHX0RwVHU0wEm+ZMMYBxMzOtg605EU0kzKs58=; b=owEBbQKS/ZANAwAIASCtLsZbECziAcsmYgBl5ejK1tq0FPOONhLa7oiPVFP5e5ONc2D4XjhIBYjj LqPK5VSJAjMEAAEIAB0WIQRPj7g/vng8MQxQWQQgrS7GWxAs4gUCZeXoygAKCRAgrS7GWxAs4i8YD/ 9ohvqFBW5bdZZumjj4YbMovv6fQpS1NnYUDRGRpnMu5nnO14iFhNJU+HdJ8SZg+AauL1kDsb9SD/uJ mPYFPwZowGawDXo3x9iiCIm/BjkV7nz+FHs7BSExvoOhFRUGeSd+M78DKtNkbDxe8pIgSIWLC7tuSd 2ZH97rfVtxHXXCQKReCMxJ4UYNxjuGNph29K8IxS9mE/i4WrHwp3DDsoDO0VkLWvcZra5C/JoNse8I NOna9vr8b09/1+JoyjQDzuGyOGGIGtBAGuhZLeL/7N7poU+x9NNXFjEcMbT4See5J6Eyeo+1zDV9vg jIPh4Dzx3R/+y/8lR3g7YMb86+YqEUbpjw1iJTfkr7C8bjeKa5XKSgCxyrmAZdIKMmMgmm/WZmmiEm Ma6aTBo6yGVehgNhcZrtLmRZEfE0eX6FrkcfdiNW0F23O/xPWjJnUADYjvI+j6UGNBNRAtPBoeBZtF d0YR7TXKd9iUBrM+sFivFn5tlySZWH3/ypZhdYmRNTGsW6hCrJoZQWWDDiGXVqxJjgaVy8FXvC7rVw /BYoTF+ogBO/OJNXeWxPSTGzOXquGlLJ6LhbanIXIrm1tHywcLCNDPY70dBb2pCqpn/zIbYetcHhcW lZcUCI0VRmgITIDSI7kdpmqoNR/XyOnR71jFrn6yo3AR2wvhxM1eC9htd9PA== X-Developer-Key: i=louis.chauvet@bootlin.com; a=openpgp; fpr=8B7104AE9A272D6693F527F2EC1883F55E0B40A5 X-GND-Sasl: louis.chauvet@bootlin.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Few no-op changes to remove double spaces and fix wrong alignments. Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_composer.c | 10 +++++----- drivers/gpu/drm/vkms/vkms_crtc.c | 6 ++---- drivers/gpu/drm/vkms/vkms_drv.c | 3 +-- drivers/gpu/drm/vkms/vkms_plane.c | 8 ++++---- 4 files changed, 12 insertions(+), 15 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index e7441b227b3c..c6d9b4a65809 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -96,7 +96,7 @@ static u16 lerp_u16(u16 a, u16 b, s64 t) s64 a_fp = drm_int2fixp(a); s64 b_fp = drm_int2fixp(b); - s64 delta = drm_fixp_mul(b_fp - a_fp, t); + s64 delta = drm_fixp_mul(b_fp - a_fp, t); return drm_fixp2int(a_fp + delta); } @@ -302,8 +302,8 @@ static int compose_active_planes(struct vkms_writeback_job *active_wb, void vkms_composer_worker(struct work_struct *work) { struct vkms_crtc_state *crtc_state = container_of(work, - struct vkms_crtc_state, - composer_work); + struct vkms_crtc_state, + composer_work); struct drm_crtc *crtc = crtc_state->base.crtc; struct vkms_writeback_job *active_wb = crtc_state->active_writeback; struct vkms_output *out = drm_crtc_to_vkms_output(crtc); @@ -328,7 +328,7 @@ void vkms_composer_worker(struct work_struct *work) crtc_state->gamma_lut.base = (struct drm_color_lut *)crtc->state->gamma_lut->data; crtc_state->gamma_lut.lut_length = crtc->state->gamma_lut->length / sizeof(struct drm_color_lut); - max_lut_index_fp = drm_int2fixp(crtc_state->gamma_lut.lut_length - 1); + max_lut_index_fp = drm_int2fixp(crtc_state->gamma_lut.lut_length - 1); crtc_state->gamma_lut.channel_value2index_ratio = drm_fixp_div(max_lut_index_fp, u16_max_fp); @@ -367,7 +367,7 @@ void vkms_composer_worker(struct work_struct *work) drm_crtc_add_crc_entry(crtc, true, frame_start++, &crc32); } -static const char * const pipe_crc_sources[] = {"auto"}; +static const char *const pipe_crc_sources[] = { "auto" }; const char *const *vkms_get_crc_sources(struct drm_crtc *crtc, size_t *count) diff --git a/drivers/gpu/drm/vkms/vkms_crtc.c b/drivers/gpu/drm/vkms/vkms_crtc.c index 61e500b8c9da..7586ae2e1dd3 100644 --- a/drivers/gpu/drm/vkms/vkms_crtc.c +++ b/drivers/gpu/drm/vkms/vkms_crtc.c @@ -191,8 +191,7 @@ static int vkms_crtc_atomic_check(struct drm_crtc *crtc, return ret; drm_for_each_plane_mask(plane, crtc->dev, crtc_state->plane_mask) { - plane_state = drm_atomic_get_existing_plane_state(crtc_state->state, - plane); + plane_state = drm_atomic_get_existing_plane_state(crtc_state->state, plane); WARN_ON(!plane_state); if (!plane_state->visible) @@ -208,8 +207,7 @@ static int vkms_crtc_atomic_check(struct drm_crtc *crtc, i = 0; drm_for_each_plane_mask(plane, crtc->dev, crtc_state->plane_mask) { - plane_state = drm_atomic_get_existing_plane_state(crtc_state->state, - plane); + plane_state = drm_atomic_get_existing_plane_state(crtc_state->state, plane); if (!plane_state->visible) continue; diff --git a/drivers/gpu/drm/vkms/vkms_drv.c b/drivers/gpu/drm/vkms/vkms_drv.c index dd0af086e7fa..83e6c9b9ff46 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.c +++ b/drivers/gpu/drm/vkms/vkms_drv.c @@ -81,8 +81,7 @@ static void vkms_atomic_commit_tail(struct drm_atomic_state *old_state) drm_atomic_helper_wait_for_flip_done(dev, old_state); for_each_old_crtc_in_state(old_state, crtc, old_crtc_state, i) { - struct vkms_crtc_state *vkms_state = - to_vkms_crtc_state(old_crtc_state); + struct vkms_crtc_state *vkms_state = to_vkms_crtc_state(old_crtc_state); flush_work(&vkms_state->composer_work); } diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index e5c625ab8e3e..5a8d295e65f2 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -117,10 +117,10 @@ static void vkms_plane_atomic_update(struct drm_plane *plane, memcpy(&frame_info->map, &shadow_plane_state->data, sizeof(frame_info->map)); drm_framebuffer_get(frame_info->fb); frame_info->rotation = drm_rotation_simplify(new_state->rotation, DRM_MODE_ROTATE_0 | - DRM_MODE_ROTATE_90 | - DRM_MODE_ROTATE_270 | - DRM_MODE_REFLECT_X | - DRM_MODE_REFLECT_Y); + DRM_MODE_ROTATE_90 | + DRM_MODE_ROTATE_270 | + DRM_MODE_REFLECT_X | + DRM_MODE_REFLECT_Y); drm_rect_rotate(&frame_info->rotated, drm_rect_width(&frame_info->rotated), drm_rect_height(&frame_info->rotated), frame_info->rotation); From patchwork Mon Mar 4 15:28:07 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Louis Chauvet X-Patchwork-Id: 13580736 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 67638C5478C for ; Mon, 4 Mar 2024 15:29:29 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 1E9FD1122A9; Mon, 4 Mar 2024 15:29:27 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=bootlin.com header.i=@bootlin.com header.b="hXhsboYK"; dkim-atps=neutral Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) by gabe.freedesktop.org (Postfix) with ESMTPS id F37DA11227C for ; Mon, 4 Mar 2024 15:29:22 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id A18231C000C; Mon, 4 Mar 2024 15:29:20 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1709566161; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=jiFoWvvgAV8DiexHt8SOwI23FzpgbcJPyIxwHbI/8Nc=; b=hXhsboYKSftxDDsOcgabRBWsPAy3Uwu5Cqiodq1CL7HBSoBCUP+/A+zyg+fv+330D1nZoG UCEKpdeq9RnCpRGQ0Qhkx4A4QI1DMBFZZozROKoSNudHwm7iGnYlaZV2tWV2vt9oKWBCPI 9sKQCrQTAj7I3LlpjP9Y8oOIs+QIJNYbSN34OCmGw5Iz6xrNR2Yne8DA9I2qfxqm6bUaWI zrD6Gxd2BpZ1kXgLtmEYQDq++8++/ZFwPkOSim4HDjcR2PCsHIm0SeOLp/MGltd77hiKP9 BVvmytnCiUpfjaUME9BgOY7/ilKtEFZCK43nxsuNDHsLRcglPfekHdIRCKEfCw== From: Louis Chauvet Date: Mon, 04 Mar 2024 16:28:07 +0100 Subject: [PATCH v4 02/14] drm/vkms: Use drm_frame directly MIME-Version: 1.0 Message-Id: <20240304-yuv-v4-2-76beac8e9793@bootlin.com> References: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> In-Reply-To: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> To: Rodrigo Siqueira , Melissa Wen , =?utf-8?q?Ma=C3=ADra_Canal?= , Haneen Mohammed , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , arthurgrillo@riseup.net, Jonathan Corbet , pekka.paalanen@haloniitty.fi Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, jeremie.dautheribes@bootlin.com, miquel.raynal@bootlin.com, thomas.petazzoni@bootlin.com, seanpaul@google.com, marcheu@google.com, nicolejadeyee@google.com, Louis Chauvet X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=4080; i=louis.chauvet@bootlin.com; h=from:subject:message-id; bh=N7pM5FLs21FNL8hsQWxNphWYncmcUeuWyWea5GV/zSA=; b=owEBbQKS/ZANAwAIASCtLsZbECziAcsmYgBl5ejKWjD5hQ40DfvQsgx2cfkxrSI5AgjQdQj2cx9d EPinh/2JAjMEAAEIAB0WIQRPj7g/vng8MQxQWQQgrS7GWxAs4gUCZeXoygAKCRAgrS7GWxAs4ghkEA CUD6pldr2kgjDm/IJbGMJDkpFrVkyzlDPbX5N7y6jf+KYbBk+xHHcUuYACGW46ckvzvxSu4YdQI4sf Dm86BO2j07TIohYqgdpeAClFnRKQ7RSPqUR+qneGidHHqqwZVSL2QUhr4lgtTcAm3LG3CgI4f2fAB0 8S1ZC2SQQ2P6ZKV8ANq4tOTGvXXmb1XfwcOwzvGsrULn7iuAxclyygs3O4qM0xOaolIcf8ZEFKLl1j Gr2yxZsm6j9v+Z/WNYzMNK2c3/SoPhNwvNFDgYx00cG32aughDg4spVVEN6UW0sF//YsV3Aa/4+8ay rIOO0JzF9zNlc5Oh7zlKoKnEJLeEeS9lgFe9x5sEssHHQoqRgXrMB1tbUL4Wesb6bwBNWeGb1yHnPw a69CmzKlfpwR8TLDWxTGVExrqsiUE3nL95xNXnnBgRcnkrV5r0mVQ1HE7CxdVAGg9q5j+CkgZaeaH+ xSTUdVo+HUBhOuOiULSsVoaQXliw4CO+QlCtFva5EgP64A8vrfyhYTnU2n1bLMG0GSsYl9Hydj/sMj 6as+y0bU2KDgRgbFz7q7g7+OjRLbfg5fg8IX48RDbJ1sfcxFrDpAgtxn/Jbncu4LMJPlDENhqV3OOD UPGqBFri7IuJaRucHQIO3JvFQOudaNOIkqrO92JusENALsMLUxHzs0HF+AJA== X-Developer-Key: i=louis.chauvet@bootlin.com; a=openpgp; fpr=8B7104AE9A272D6693F527F2EC1883F55E0B40A5 X-GND-Sasl: louis.chauvet@bootlin.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Arthur Grillo Remove intermidiary variables and access the variables directly from drm_frame. These changes should be noop. Signed-off-by: Arthur Grillo Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_drv.h | 3 --- drivers/gpu/drm/vkms/vkms_formats.c | 12 +++++++----- drivers/gpu/drm/vkms/vkms_plane.c | 3 --- drivers/gpu/drm/vkms/vkms_writeback.c | 5 ----- 4 files changed, 7 insertions(+), 16 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 8f5710debb1e..b4b357447292 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -31,9 +31,6 @@ struct vkms_frame_info { struct drm_rect rotated; struct iosys_map map[DRM_FORMAT_MAX_PLANES]; unsigned int rotation; - unsigned int offset; - unsigned int pitch; - unsigned int cpp; }; struct pixel_argb_u16 { diff --git a/drivers/gpu/drm/vkms/vkms_formats.c b/drivers/gpu/drm/vkms/vkms_formats.c index 36046b12f296..172830a3936a 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.c +++ b/drivers/gpu/drm/vkms/vkms_formats.c @@ -11,8 +11,10 @@ static size_t pixel_offset(const struct vkms_frame_info *frame_info, int x, int y) { - return frame_info->offset + (y * frame_info->pitch) - + (x * frame_info->cpp); + struct drm_framebuffer *fb = frame_info->fb; + + return fb->offsets[0] + (y * fb->pitches[0]) + + (x * fb->format->cpp[0]); } /* @@ -131,12 +133,12 @@ void vkms_compose_row(struct line_buffer *stage_buffer, struct vkms_plane_state u8 *src_pixels = get_packed_src_addr(frame_info, y); int limit = min_t(size_t, drm_rect_width(&frame_info->dst), stage_buffer->n_pixels); - for (size_t x = 0; x < limit; x++, src_pixels += frame_info->cpp) { + for (size_t x = 0; x < limit; x++, src_pixels += frame_info->fb->format->cpp[0]) { int x_pos = get_x_position(frame_info, limit, x); if (drm_rotation_90_or_270(frame_info->rotation)) src_pixels = get_packed_src_addr(frame_info, x + frame_info->rotated.y1) - + frame_info->cpp * y; + + frame_info->fb->format->cpp[0] * y; plane->pixel_read(src_pixels, &out_pixels[x_pos]); } @@ -223,7 +225,7 @@ void vkms_writeback_row(struct vkms_writeback_job *wb, struct pixel_argb_u16 *in_pixels = src_buffer->pixels; int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), src_buffer->n_pixels); - for (size_t x = 0; x < x_limit; x++, dst_pixels += frame_info->cpp) + for (size_t x = 0; x < x_limit; x++, dst_pixels += frame_info->fb->format->cpp[0]) wb->pixel_write(dst_pixels, &in_pixels[x]); } diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index 5a8d295e65f2..21b5adfb44aa 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -125,9 +125,6 @@ static void vkms_plane_atomic_update(struct drm_plane *plane, drm_rect_rotate(&frame_info->rotated, drm_rect_width(&frame_info->rotated), drm_rect_height(&frame_info->rotated), frame_info->rotation); - frame_info->offset = fb->offsets[0]; - frame_info->pitch = fb->pitches[0]; - frame_info->cpp = fb->format->cpp[0]; vkms_plane_state->pixel_read = get_pixel_conversion_function(fmt); } diff --git a/drivers/gpu/drm/vkms/vkms_writeback.c b/drivers/gpu/drm/vkms/vkms_writeback.c index bc724cbd5e3a..c8582df1f739 100644 --- a/drivers/gpu/drm/vkms/vkms_writeback.c +++ b/drivers/gpu/drm/vkms/vkms_writeback.c @@ -149,11 +149,6 @@ static void vkms_wb_atomic_commit(struct drm_connector *conn, crtc_state->active_writeback = active_wb; crtc_state->wb_pending = true; spin_unlock_irq(&output->composer_lock); - - wb_frame_info->offset = fb->offsets[0]; - wb_frame_info->pitch = fb->pitches[0]; - wb_frame_info->cpp = fb->format->cpp[0]; - drm_writeback_queue_job(wb_conn, connector_state); active_wb->pixel_write = get_pixel_write_function(wb_format); drm_rect_init(&wb_frame_info->src, 0, 0, crtc_width, crtc_height); From patchwork Mon Mar 4 15:28:08 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Louis Chauvet X-Patchwork-Id: 13580735 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C52BBC54E4A for ; Mon, 4 Mar 2024 15:29:27 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 6B2A211227C; Mon, 4 Mar 2024 15:29:26 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=bootlin.com header.i=@bootlin.com header.b="A40f85aL"; dkim-atps=neutral Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) by gabe.freedesktop.org (Postfix) with ESMTPS id F30DA11228A for ; Mon, 4 Mar 2024 15:29:23 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id AB8EB1C0003; Mon, 4 Mar 2024 15:29:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1709566162; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=UoEJVitgQdwqzYit9x2fRkuhzwqFW+P/Z98aACWVEW8=; b=A40f85aLh9dvPmu6NQ4HVs515kE5Vo2AFNqoZxD0H8wTrxVzZg1IfGJ24QMKN9cQZCOBSZ 8QdfhBf7wYlU2xvmJkwxGOa/tYr7IVHuhE6aIT5varV4B5PqeOB96jt6ojN9MZLP/etuAY sH0ZA76Fr00Zhu3N+YCTvcY4Yl/4jeJrjv20NvU7Tzia0cyQkcYH/k8SHm4X6UQefUGLSs hn1pzeD2H08eiLA3igrkkM1lvV8npLX+FQr+3l/vDKGSEj60htcQd4YP1MkrVp8397y8/H tDrHvgMEXetGeNVL3i4NK/+LVKc1NS1+8me7N1E3jh3Uk2CntdaPXdTpcUPAGA== From: Louis Chauvet Date: Mon, 04 Mar 2024 16:28:08 +0100 Subject: [PATCH v4 03/14] drm/vkms: write/update the documentation for pixel conversion and pixel write functions MIME-Version: 1.0 Message-Id: <20240304-yuv-v4-3-76beac8e9793@bootlin.com> References: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> In-Reply-To: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> To: Rodrigo Siqueira , Melissa Wen , =?utf-8?q?Ma=C3=ADra_Canal?= , Haneen Mohammed , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , arthurgrillo@riseup.net, Jonathan Corbet , pekka.paalanen@haloniitty.fi Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, jeremie.dautheribes@bootlin.com, miquel.raynal@bootlin.com, thomas.petazzoni@bootlin.com, seanpaul@google.com, marcheu@google.com, nicolejadeyee@google.com, Louis Chauvet X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=7282; i=louis.chauvet@bootlin.com; h=from:subject:message-id; bh=rAa69AVNvXwStTD/zFUG8N7xq95vym8ycf+nNk+Pqpg=; b=owEBbQKS/ZANAwAIASCtLsZbECziAcsmYgBl5ejLsCb3xgbo3eBxhb/+Zom9MLwlxhoqz5/HCrlI 1rnOZ76JAjMEAAEIAB0WIQRPj7g/vng8MQxQWQQgrS7GWxAs4gUCZeXoywAKCRAgrS7GWxAs4iiMD/ 9ihUJJRxg0jAcIVdcO+M/zG6DiWT7lXk6c4RZ1s2knRRgJlGyx1T3UfZl8PxTIDo+UFkMqDvcCHF9N VgdhgEmzOyQTEWPhPMP/1B4MrX1GPWUuR0KQBVW3fcXVQMtef5jt19v3FOPrN2/TM4fCZo7iw7p1Ed SGseHVUfeBWuc3wXA5xbdNezswG3daF89bhm3mgQ+OjKnopkC9IvHGObxNFKvdNMMSSQIJZlhrpna8 Ic7KeSBmvIspO5vulIkMtKLE/a2jErY4bd1sDMW3knlRp0Hy72XpkjGOLxEvWHkKffM2qXjDr2i9Lt f5N/r8NJpUET2f7dqCwH512eExZB1yjZeVrZvff2UGV3Ivz17ZmUIho621jGi3vYAySRI3QKfz+CKg LWXSKpS0UGHTWKWn5m4ezAr48ImFzGcSFrpSV8izhIg6fsp2ygAZG4rbtCiKJ4kQnfFgTPYgJ7Z8Bt qmlYsSSXfqXCZcfZ+qwbSy1OAExrj845GIqHI3KnZJk1iD8x4NVnbF0Bjwyt/390QewsuqWbZs0yk+ tgtMsah/IribpsJ+g/4NAqtUM+Z9HUuhZNQtzthH2XY90zFA84gVYdM8OK3hSGvabY4tv4JQis87SH lSnlGCOlLzAuO2uLPkZYLYZq08bAEQ+L3C23Dgk3lj+BAyUsxyed7miBHpIg== X-Developer-Key: i=louis.chauvet@bootlin.com; a=openpgp; fpr=8B7104AE9A272D6693F527F2EC1883F55E0B40A5 X-GND-Sasl: louis.chauvet@bootlin.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Add some documentation on pixel conversion functions. Update of outdated comments for pixel_write functions. Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_composer.c | 7 ++++ drivers/gpu/drm/vkms/vkms_drv.h | 13 ++++++++ drivers/gpu/drm/vkms/vkms_formats.c | 62 ++++++++++++++++++++++++++++++------ 3 files changed, 73 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index c6d9b4a65809..da0651a94c9b 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -189,6 +189,13 @@ static void blend(struct vkms_writeback_job *wb, size_t crtc_y_limit = crtc_state->base.crtc->mode.vdisplay; + /* + * The planes are composed line-by-line to avoid heavy memory usage. It is a necessary + * complexity to avoid poor blending performance. + * + * The function vkms_compose_row is used to read a line, pixel-by-pixel, into the staging + * buffer. + */ for (size_t y = 0; y < crtc_y_limit; y++) { fill_background(&background_color, output_buffer); diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index b4b357447292..18086423a3a7 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -25,6 +25,17 @@ #define VKMS_LUT_SIZE 256 +/** + * struct vkms_frame_info - structure to store the state of a frame + * + * @fb: backing drm framebuffer + * @src: source rectangle of this frame in the source framebuffer + * @dst: destination rectangle in the crtc buffer + * @map: see drm_shadow_plane_state@data + * @rotation: rotation applied to the source. + * + * @src and @dst should have the same size modulo the rotation. + */ struct vkms_frame_info { struct drm_framebuffer *fb; struct drm_rect src, dst; @@ -52,6 +63,8 @@ struct vkms_writeback_job { * vkms_plane_state - Driver specific plane state * @base: base plane state * @frame_info: data required for composing computation + * @pixel_read: function to read a pixel in this plane. The creator of a vkms_plane_state must + * ensure that this pointer is valid */ struct vkms_plane_state { struct drm_shadow_plane_state base; diff --git a/drivers/gpu/drm/vkms/vkms_formats.c b/drivers/gpu/drm/vkms/vkms_formats.c index 172830a3936a..6e3dc8682ff9 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.c +++ b/drivers/gpu/drm/vkms/vkms_formats.c @@ -9,6 +9,18 @@ #include "vkms_formats.h" +/** + * pixel_offset() - Get the offset of the pixel at coordinates x/y in the first plane + * + * @frame_info: Buffer metadata + * @x: The x coordinate of the wanted pixel in the buffer + * @y: The y coordinate of the wanted pixel in the buffer + * + * The caller must ensure that the framebuffer associated with this request uses a pixel format + * where block_h == block_w == 1. + * If this requirement is not fulfilled, the resulting offset can point to an other pixel or + * outside of the buffer. + */ static size_t pixel_offset(const struct vkms_frame_info *frame_info, int x, int y) { struct drm_framebuffer *fb = frame_info->fb; @@ -17,18 +29,22 @@ static size_t pixel_offset(const struct vkms_frame_info *frame_info, int x, int + (x * fb->format->cpp[0]); } -/* - * packed_pixels_addr - Get the pointer to pixel of a given pair of coordinates +/** + * packed_pixels_addr() - Get the pointer to the block containing the pixel at the given + * coordinates * * @frame_info: Buffer metadata - * @x: The x(width) coordinate of the 2D buffer - * @y: The y(Heigth) coordinate of the 2D buffer + * @x: The x(width) coordinate inside the plane + * @y: The y(height) coordinate inside the plane * * Takes the information stored in the frame_info, a pair of coordinates, and * returns the address of the first color channel. * This function assumes the channels are packed together, i.e. a color channel * comes immediately after another in the memory. And therefore, this function * doesn't work for YUV with chroma subsampling (e.g. YUV420 and NV21). + * + * The caller must ensure that the framebuffer associated with this request uses a pixel format + * where block_h == block_w == 1, otherwise the returned pointer can be outside the buffer. */ static void *packed_pixels_addr(const struct vkms_frame_info *frame_info, int x, int y) @@ -53,6 +69,13 @@ static int get_x_position(const struct vkms_frame_info *frame_info, int limit, i return x; } +/* + * The following functions take pixel data from the buffer and convert them to the format + * ARGB16161616 in out_pixel. + * + * They are used in the `vkms_compose_row` function to handle multiple formats. + */ + static void ARGB8888_to_argb_u16(u8 *src_pixels, struct pixel_argb_u16 *out_pixel) { /* @@ -145,12 +168,11 @@ void vkms_compose_row(struct line_buffer *stage_buffer, struct vkms_plane_state } /* - * The following functions take an line of argb_u16 pixels from the - * src_buffer, convert them to a specific format, and store them in the - * destination. + * The following functions take one argb_u16 pixel and convert it to a specific format. The + * result is stored in @dst_pixels. * - * They are used in the `compose_active_planes` to convert and store a line - * from the src_buffer to the writeback buffer. + * They are used in the `vkms_writeback_row` to convert and store a pixel from the src_buffer to + * the writeback buffer. */ static void argb_u16_to_ARGB8888(u8 *dst_pixels, struct pixel_argb_u16 *in_pixel) { @@ -216,6 +238,14 @@ static void argb_u16_to_RGB565(u8 *dst_pixels, struct pixel_argb_u16 *in_pixel) *pixels = cpu_to_le16(r << 11 | g << 5 | b); } +/** + * Generic loop for all supported writeback format. It is executed just after the blending to + * write a line in the writeback buffer. + * + * @wb: Job where to insert the final image + * @src_buffer: Line to write + * @y: Row to write in the writeback buffer + */ void vkms_writeback_row(struct vkms_writeback_job *wb, const struct line_buffer *src_buffer, int y) { @@ -229,6 +259,13 @@ void vkms_writeback_row(struct vkms_writeback_job *wb, wb->pixel_write(dst_pixels, &in_pixels[x]); } +/** + * Retrieve the correct read_pixel function for a specific format. + * The returned pointer is NULL for unsupported pixel formats. The caller must ensure that the + * pointer is valid before using it in a vkms_plane_state. + * + * @format: DRM_FORMAT_* value for which to obtain a conversion function (see [drm_fourcc.h]) + */ void *get_pixel_conversion_function(u32 format) { switch (format) { @@ -247,6 +284,13 @@ void *get_pixel_conversion_function(u32 format) } } +/** + * Retrieve the correct write_pixel function for a specific format. + * The returned pointer is NULL for unsupported pixel formats. The caller must ensure that the + * pointer is valid before using it in a vkms_writeback_job. + * + * @format: DRM_FORMAT_* value for which to obtain a conversion function (see [drm_fourcc.h]) + */ void *get_pixel_write_function(u32 format) { switch (format) { From patchwork Mon Mar 4 15:28:09 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Louis Chauvet X-Patchwork-Id: 13580734 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 66120C48BF6 for ; Mon, 4 Mar 2024 15:29:27 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8E6691122A5; Mon, 4 Mar 2024 15:29:26 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=bootlin.com header.i=@bootlin.com header.b="UrT6c6Sj"; dkim-atps=neutral Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) by gabe.freedesktop.org (Postfix) with ESMTPS id 16C331122A6 for ; Mon, 4 Mar 2024 15:29:24 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id B2F561C0004; Mon, 4 Mar 2024 15:29:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1709566163; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=AYBfso6Q+rkxcM5HC6d5eJGza1FTaahkzypsqttBm4M=; b=UrT6c6SjQQHWLIVzvWYWbFmu+gC8RaozQ+xBygt84KRQaqxkLfTd2aE5XrTk1MLyrbu8Wr DMJ/PCPAhklP+dvyX+MnuhF8Av8oIrdC1vCOIj1O+xvzNniT0nCReq3bjCw0MC5mJFTjFM taP9pte2iB3kQglx9YjRE23mLX4nP+L8I9SHO60x+JucWJkgjGg0n/ErDSIK/Zdrqi2vh4 e0AKcQSLf+xpLTw4YI7VXsIQ8diQ5q2BeMl1dj8y/sv+1Ef2x0cxKnVjHZgdRk2kCaYLG2 GM7FN1FdKxSqsKiXSvdNczWNBqC+uq5M1p0eYwK5BXq4dSONqvpYJnjxL7TAuw== From: Louis Chauvet Date: Mon, 04 Mar 2024 16:28:09 +0100 Subject: [PATCH v4 04/14] drm/vkms: Add typedef and documentation for pixel_read and pixel_write functions MIME-Version: 1.0 Message-Id: <20240304-yuv-v4-4-76beac8e9793@bootlin.com> References: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> In-Reply-To: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> To: Rodrigo Siqueira , Melissa Wen , =?utf-8?q?Ma=C3=ADra_Canal?= , Haneen Mohammed , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , arthurgrillo@riseup.net, Jonathan Corbet , pekka.paalanen@haloniitty.fi Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, jeremie.dautheribes@bootlin.com, miquel.raynal@bootlin.com, thomas.petazzoni@bootlin.com, seanpaul@google.com, marcheu@google.com, nicolejadeyee@google.com, Louis Chauvet X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=12639; i=louis.chauvet@bootlin.com; h=from:subject:message-id; bh=e0KtaUwdvkxJwLoifx11GPaeYI4Zniu/rrdGgqSbxp0=; b=kA0DAAgBIK0uxlsQLOIByyZiAGXl6MvI/yq0lzM/zNXPgqGJ+VIhFNeXdxaQBdkPegSrXJBvpokC MwQAAQgAHRYhBE+PuD++eDwxDFBZBCCtLsZbECziBQJl5ejLAAoJECCtLsZbECzijlIQAM6/HdBIei 2CFJoUSgpxJOL34lW+GolGISWnyokZRJyY7FLYWTwFc+XNMSF2HWBbLiIveBZj2/4YOmqttWSjKtAl +rqsrPFzceOyyiOmgQ9MQpe+CHQEnTFljukPbZi4PeCnEQJ6BP0E8ZkC4fKbXC8A3qoBPQ3sxl8+n9 o+BI3qi+lz5+KUDeT2rT4nlAN6pPYlG09RVnsRNdQxmk2XT6jqcK2GQkGxuaavssu/LMOVNADCg57T QfWyaOnfVosXNOdbYZM6RCrlke3VLKTTJ57u4ZVE4NNpy3f+7zyxsTXZ0r4GDQJrQvnDFJCFNnMbhx vIW3Mt+NykuOoXHAAomy3FW9EifaVgW+h5ruLpsrSDnKVtcaMYyiA0/iOJd17rYwjkJXSgv7yqQQs7 7YHj66KAjYSVmuLHuh8ohAMqVRTJh2nYsQMD/qTrlCXzB6DIE4psRCl9UAchTCxmFEGTAj1QkMytEV tUmKgWAY19Gp3MbiQc0b0VQeKgCYiDcMMkuwzjO81F72gtpPegU5jhEyWcjrDZc3Ryjip39HsKbg5J Msd+ZJsIsnRsa1FUe6w8QVt0RVWbUodbCEZXUSgHYio69C8OmW3LqLiRGMHl6td8ZKUzSlRB378U++ ae4sHU89avCUyxJYrZp3oYWibpG2/szLplv+mu2MObAZpzQZJg X-Developer-Key: i=louis.chauvet@bootlin.com; a=openpgp; fpr=8B7104AE9A272D6693F527F2EC1883F55E0B40A5 X-GND-Sasl: louis.chauvet@bootlin.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Introduce two typedefs: pixel_read_t and pixel_write_t. It allows the compiler to check if the passed functions take the correct arguments. Such typedefs will help ensuring consistency across the code base in case of update of these prototypes. Rename input/output variable in a consistent way between read_line and write_line. A warn has been added in get_pixel_*_function to alert when an unsupported pixel format is requested. As those formats are checked before atomic_update callbacks, it should never append. Document for those typedefs. Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_drv.h | 23 ++++++- drivers/gpu/drm/vkms/vkms_formats.c | 122 ++++++++++++++++++++---------------- drivers/gpu/drm/vkms/vkms_formats.h | 4 +- drivers/gpu/drm/vkms/vkms_plane.c | 2 +- 4 files changed, 93 insertions(+), 58 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 18086423a3a7..4bfc62d26f08 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -53,12 +53,31 @@ struct line_buffer { struct pixel_argb_u16 *pixels; }; +/** + * typedef pixel_write_t - These functions are used to read a pixel from a + * `struct pixel_argb_u16*`, convert it in a specific format and write it in the @dst_pixels + * buffer. + * + * @out_pixel: destination address to write the pixel + * @in_pixel: pixel to write + */ +typedef void (*pixel_write_t)(u8 *out_pixel, struct pixel_argb_u16 *in_pixel); + struct vkms_writeback_job { struct iosys_map data[DRM_FORMAT_MAX_PLANES]; struct vkms_frame_info wb_frame_info; - void (*pixel_write)(u8 *dst_pixels, struct pixel_argb_u16 *in_pixel); + pixel_write_t pixel_write; }; +/** + * typedef pixel_read_t - These functions are used to read a pixel in the source frame, + * convert it to `struct pixel_argb_u16` and write it to @out_pixel. + * + * @in_pixel: Pointer to the pixel to read + * @out_pixel: Pointer to write the converted pixel + */ +typedef void (*pixel_read_t)(u8 *in_pixel, struct pixel_argb_u16 *out_pixel); + /** * vkms_plane_state - Driver specific plane state * @base: base plane state @@ -69,7 +88,7 @@ struct vkms_writeback_job { struct vkms_plane_state { struct drm_shadow_plane_state base; struct vkms_frame_info *frame_info; - void (*pixel_read)(u8 *src_buffer, struct pixel_argb_u16 *out_pixel); + pixel_read_t pixel_read; }; struct vkms_plane { diff --git a/drivers/gpu/drm/vkms/vkms_formats.c b/drivers/gpu/drm/vkms/vkms_formats.c index 6e3dc8682ff9..393c73caad72 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.c +++ b/drivers/gpu/drm/vkms/vkms_formats.c @@ -76,7 +76,7 @@ static int get_x_position(const struct vkms_frame_info *frame_info, int limit, i * They are used in the `vkms_compose_row` function to handle multiple formats. */ -static void ARGB8888_to_argb_u16(u8 *src_pixels, struct pixel_argb_u16 *out_pixel) +static void ARGB8888_to_argb_u16(u8 *in_pixel, struct pixel_argb_u16 *out_pixel) { /* * The 257 is the "conversion ratio". This number is obtained by the @@ -84,48 +84,48 @@ static void ARGB8888_to_argb_u16(u8 *src_pixels, struct pixel_argb_u16 *out_pixe * the best color value in a pixel format with more possibilities. * A similar idea applies to others RGB color conversions. */ - out_pixel->a = (u16)src_pixels[3] * 257; - out_pixel->r = (u16)src_pixels[2] * 257; - out_pixel->g = (u16)src_pixels[1] * 257; - out_pixel->b = (u16)src_pixels[0] * 257; + out_pixel->a = (u16)in_pixel[3] * 257; + out_pixel->r = (u16)in_pixel[2] * 257; + out_pixel->g = (u16)in_pixel[1] * 257; + out_pixel->b = (u16)in_pixel[0] * 257; } -static void XRGB8888_to_argb_u16(u8 *src_pixels, struct pixel_argb_u16 *out_pixel) +static void XRGB8888_to_argb_u16(u8 *in_pixel, struct pixel_argb_u16 *out_pixel) { out_pixel->a = (u16)0xffff; - out_pixel->r = (u16)src_pixels[2] * 257; - out_pixel->g = (u16)src_pixels[1] * 257; - out_pixel->b = (u16)src_pixels[0] * 257; + out_pixel->r = (u16)in_pixel[2] * 257; + out_pixel->g = (u16)in_pixel[1] * 257; + out_pixel->b = (u16)in_pixel[0] * 257; } -static void ARGB16161616_to_argb_u16(u8 *src_pixels, struct pixel_argb_u16 *out_pixel) +static void ARGB16161616_to_argb_u16(u8 *in_pixel, struct pixel_argb_u16 *out_pixel) { - u16 *pixels = (u16 *)src_pixels; + u16 *pixel = (u16 *)in_pixel; - out_pixel->a = le16_to_cpu(pixels[3]); - out_pixel->r = le16_to_cpu(pixels[2]); - out_pixel->g = le16_to_cpu(pixels[1]); - out_pixel->b = le16_to_cpu(pixels[0]); + out_pixel->a = le16_to_cpu(pixel[3]); + out_pixel->r = le16_to_cpu(pixel[2]); + out_pixel->g = le16_to_cpu(pixel[1]); + out_pixel->b = le16_to_cpu(pixel[0]); } -static void XRGB16161616_to_argb_u16(u8 *src_pixels, struct pixel_argb_u16 *out_pixel) +static void XRGB16161616_to_argb_u16(u8 *in_pixel, struct pixel_argb_u16 *out_pixel) { - u16 *pixels = (u16 *)src_pixels; + u16 *pixel = (u16 *)in_pixel; out_pixel->a = (u16)0xffff; - out_pixel->r = le16_to_cpu(pixels[2]); - out_pixel->g = le16_to_cpu(pixels[1]); - out_pixel->b = le16_to_cpu(pixels[0]); + out_pixel->r = le16_to_cpu(pixel[2]); + out_pixel->g = le16_to_cpu(pixel[1]); + out_pixel->b = le16_to_cpu(pixel[0]); } -static void RGB565_to_argb_u16(u8 *src_pixels, struct pixel_argb_u16 *out_pixel) +static void RGB565_to_argb_u16(u8 *in_pixel, struct pixel_argb_u16 *out_pixel) { - u16 *pixels = (u16 *)src_pixels; + u16 *pixel = (u16 *)in_pixel; s64 fp_rb_ratio = drm_fixp_div(drm_int2fixp(65535), drm_int2fixp(31)); s64 fp_g_ratio = drm_fixp_div(drm_int2fixp(65535), drm_int2fixp(63)); - u16 rgb_565 = le16_to_cpu(*pixels); + u16 rgb_565 = le16_to_cpu(*pixel); s64 fp_r = drm_int2fixp((rgb_565 >> 11) & 0x1f); s64 fp_g = drm_int2fixp((rgb_565 >> 5) & 0x3f); s64 fp_b = drm_int2fixp(rgb_565 & 0x1f); @@ -169,12 +169,12 @@ void vkms_compose_row(struct line_buffer *stage_buffer, struct vkms_plane_state /* * The following functions take one argb_u16 pixel and convert it to a specific format. The - * result is stored in @dst_pixels. + * result is stored in @out_pixel. * * They are used in the `vkms_writeback_row` to convert and store a pixel from the src_buffer to * the writeback buffer. */ -static void argb_u16_to_ARGB8888(u8 *dst_pixels, struct pixel_argb_u16 *in_pixel) +static void argb_u16_to_ARGB8888(u8 *out_pixel, struct pixel_argb_u16 *in_pixel) { /* * This sequence below is important because the format's byte order is @@ -186,43 +186,43 @@ static void argb_u16_to_ARGB8888(u8 *dst_pixels, struct pixel_argb_u16 *in_pixel * | Addr + 2 | = Red channel * | Addr + 3 | = Alpha channel */ - dst_pixels[3] = DIV_ROUND_CLOSEST(in_pixel->a, 257); - dst_pixels[2] = DIV_ROUND_CLOSEST(in_pixel->r, 257); - dst_pixels[1] = DIV_ROUND_CLOSEST(in_pixel->g, 257); - dst_pixels[0] = DIV_ROUND_CLOSEST(in_pixel->b, 257); + out_pixel[3] = DIV_ROUND_CLOSEST(in_pixel->a, 257); + out_pixel[2] = DIV_ROUND_CLOSEST(in_pixel->r, 257); + out_pixel[1] = DIV_ROUND_CLOSEST(in_pixel->g, 257); + out_pixel[0] = DIV_ROUND_CLOSEST(in_pixel->b, 257); } -static void argb_u16_to_XRGB8888(u8 *dst_pixels, struct pixel_argb_u16 *in_pixel) +static void argb_u16_to_XRGB8888(u8 *out_pixel, struct pixel_argb_u16 *in_pixel) { - dst_pixels[3] = 0xff; - dst_pixels[2] = DIV_ROUND_CLOSEST(in_pixel->r, 257); - dst_pixels[1] = DIV_ROUND_CLOSEST(in_pixel->g, 257); - dst_pixels[0] = DIV_ROUND_CLOSEST(in_pixel->b, 257); + out_pixel[3] = 0xff; + out_pixel[2] = DIV_ROUND_CLOSEST(in_pixel->r, 257); + out_pixel[1] = DIV_ROUND_CLOSEST(in_pixel->g, 257); + out_pixel[0] = DIV_ROUND_CLOSEST(in_pixel->b, 257); } -static void argb_u16_to_ARGB16161616(u8 *dst_pixels, struct pixel_argb_u16 *in_pixel) +static void argb_u16_to_ARGB16161616(u8 *out_pixel, struct pixel_argb_u16 *in_pixel) { - u16 *pixels = (u16 *)dst_pixels; + u16 *pixel = (u16 *)out_pixel; - pixels[3] = cpu_to_le16(in_pixel->a); - pixels[2] = cpu_to_le16(in_pixel->r); - pixels[1] = cpu_to_le16(in_pixel->g); - pixels[0] = cpu_to_le16(in_pixel->b); + pixel[3] = cpu_to_le16(in_pixel->a); + pixel[2] = cpu_to_le16(in_pixel->r); + pixel[1] = cpu_to_le16(in_pixel->g); + pixel[0] = cpu_to_le16(in_pixel->b); } -static void argb_u16_to_XRGB16161616(u8 *dst_pixels, struct pixel_argb_u16 *in_pixel) +static void argb_u16_to_XRGB16161616(u8 *out_pixel, struct pixel_argb_u16 *in_pixel) { - u16 *pixels = (u16 *)dst_pixels; + u16 *pixel = (u16 *)out_pixel; - pixels[3] = 0xffff; - pixels[2] = cpu_to_le16(in_pixel->r); - pixels[1] = cpu_to_le16(in_pixel->g); - pixels[0] = cpu_to_le16(in_pixel->b); + pixel[3] = 0xffff; + pixel[2] = cpu_to_le16(in_pixel->r); + pixel[1] = cpu_to_le16(in_pixel->g); + pixel[0] = cpu_to_le16(in_pixel->b); } -static void argb_u16_to_RGB565(u8 *dst_pixels, struct pixel_argb_u16 *in_pixel) +static void argb_u16_to_RGB565(u8 *out_pixel, struct pixel_argb_u16 *in_pixel) { - u16 *pixels = (u16 *)dst_pixels; + u16 *pixel = (u16 *)out_pixel; s64 fp_rb_ratio = drm_fixp_div(drm_int2fixp(65535), drm_int2fixp(31)); s64 fp_g_ratio = drm_fixp_div(drm_int2fixp(65535), drm_int2fixp(63)); @@ -235,7 +235,7 @@ static void argb_u16_to_RGB565(u8 *dst_pixels, struct pixel_argb_u16 *in_pixel) u16 g = drm_fixp2int(drm_fixp_div(fp_g, fp_g_ratio)); u16 b = drm_fixp2int(drm_fixp_div(fp_b, fp_rb_ratio)); - *pixels = cpu_to_le16(r << 11 | g << 5 | b); + *pixel = cpu_to_le16(r << 11 | g << 5 | b); } /** @@ -266,7 +266,7 @@ void vkms_writeback_row(struct vkms_writeback_job *wb, * * @format: DRM_FORMAT_* value for which to obtain a conversion function (see [drm_fourcc.h]) */ -void *get_pixel_conversion_function(u32 format) +pixel_read_t get_pixel_read_function(u32 format) { switch (format) { case DRM_FORMAT_ARGB8888: @@ -280,7 +280,15 @@ void *get_pixel_conversion_function(u32 format) case DRM_FORMAT_RGB565: return &RGB565_to_argb_u16; default: - return NULL; + /* + * This is a bug in vkms_plane_atomic_check. All the supported + * format must: + * - Be listed in vkms_formats in vkms_plane.c + * - Have a pixel_read callback defined here + */ + WARN(true, "Pixel format %4cc is not supported by VKMS planes. This is a kernel bug, atomic check must forbid this configuration.\n", + format); + return (pixel_read_t)NULL; } } @@ -291,7 +299,7 @@ void *get_pixel_conversion_function(u32 format) * * @format: DRM_FORMAT_* value for which to obtain a conversion function (see [drm_fourcc.h]) */ -void *get_pixel_write_function(u32 format) +pixel_write_t get_pixel_write_function(u32 format) { switch (format) { case DRM_FORMAT_ARGB8888: @@ -305,6 +313,14 @@ void *get_pixel_write_function(u32 format) case DRM_FORMAT_RGB565: return &argb_u16_to_RGB565; default: - return NULL; + /* + * This is a bug in vkms_writeback_atomic_check. All the supported + * format must: + * - Be listed in vkms_wb_formats in vkms_writeback.c + * - Have a pixel_write callback defined here + */ + WARN(true, "Pixel format %4cc is not supported by VKMS writeback. This is a kernel bug, atomic check must forbid this configuration.\n", + format); + return (pixel_write_t)NULL; } } diff --git a/drivers/gpu/drm/vkms/vkms_formats.h b/drivers/gpu/drm/vkms/vkms_formats.h index cf59c2ed8e9a..3ecea4563254 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.h +++ b/drivers/gpu/drm/vkms/vkms_formats.h @@ -5,8 +5,8 @@ #include "vkms_drv.h" -void *get_pixel_conversion_function(u32 format); +pixel_read_t get_pixel_read_function(u32 format); -void *get_pixel_write_function(u32 format); +pixel_write_t get_pixel_write_function(u32 format); #endif /* _VKMS_FORMATS_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index 21b5adfb44aa..10e9b23dab28 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -125,7 +125,7 @@ static void vkms_plane_atomic_update(struct drm_plane *plane, drm_rect_rotate(&frame_info->rotated, drm_rect_width(&frame_info->rotated), drm_rect_height(&frame_info->rotated), frame_info->rotation); - vkms_plane_state->pixel_read = get_pixel_conversion_function(fmt); + vkms_plane_state->pixel_read = get_pixel_read_function(fmt); } static int vkms_plane_atomic_check(struct drm_plane *plane, From patchwork Mon Mar 4 15:28:10 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Louis Chauvet X-Patchwork-Id: 13580738 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C6D88C54E55 for ; Mon, 4 Mar 2024 15:29:31 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id BC01411228A; Mon, 4 Mar 2024 15:29:29 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=bootlin.com header.i=@bootlin.com header.b="bV0pt87h"; dkim-atps=neutral Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) by gabe.freedesktop.org (Postfix) with ESMTPS id F0DDF1122AD for ; Mon, 4 Mar 2024 15:29:25 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id CCA3A1C000D; Mon, 4 Mar 2024 15:29:23 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1709566164; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=OheunqzV0Tdab0ro1TCM9rlfBD5uxy5mvs2Qm0nwE9o=; b=bV0pt87hMo/ll1N/71wSKc33n13peoHTY7sQn8FB/kvaDvEc9gXpv9tg5pudkyM/aODzey kq2G8P9GliB7ZNozUZd3MVBTKSHVwgmWjkNMuD5+E/by54NRvjgN/tphf9vVrJokEROB5f y9h4ITE/qA9HqgwBwxwtr8usC27mJI/j4+ULO+R3+ZaO4TOq0AxtUfRlJd1Eko8DxIz2Nl NqLZU7IiHFuoPKx41Wr/ToRm+SQ2oxb/qNS3iqMesjIG3Nx1hf5X3y6lC7qyb5leHVSVom 18sZHe3NmJBiv7wg4PKQMvH9dBHv9TA00TLjfHTnAwrbizEfDgXm5TvCajktGg== From: Louis Chauvet Date: Mon, 04 Mar 2024 16:28:10 +0100 Subject: [PATCH v4 05/14] drm/vkms: Add dummy pixel_read/pixel_write callbacks to avoid NULL pointers MIME-Version: 1.0 Message-Id: <20240304-yuv-v4-5-76beac8e9793@bootlin.com> References: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> In-Reply-To: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> To: Rodrigo Siqueira , Melissa Wen , =?utf-8?q?Ma=C3=ADra_Canal?= , Haneen Mohammed , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , arthurgrillo@riseup.net, Jonathan Corbet , pekka.paalanen@haloniitty.fi Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, jeremie.dautheribes@bootlin.com, miquel.raynal@bootlin.com, thomas.petazzoni@bootlin.com, seanpaul@google.com, marcheu@google.com, nicolejadeyee@google.com, Louis Chauvet X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=4457; i=louis.chauvet@bootlin.com; h=from:subject:message-id; bh=osXDzXENgU45GirTmc0kFbEH2mwwSMJk7kYLAHdAPlA=; b=owEBbQKS/ZANAwAIASCtLsZbECziAcsmYgBl5ejLXYtmd0/p9yal0gzpyvbinfGHAUv3kwIP8EXW iU5g/fSJAjMEAAEIAB0WIQRPj7g/vng8MQxQWQQgrS7GWxAs4gUCZeXoywAKCRAgrS7GWxAs4qJsEA CJYciBAlkAVuthTsMAiF6bAb1eWIKhySsuBsayNkZRAgWobjTzKQsO7f3ybhQQFU8nJ4HfFC4mXXiz S5mbdH0M0WxYHUOvMTq99YGn8ubbE8/XZOfTg0DQSqAtrhFSkBPpIn+qzE4kG6rbj8jPMFE+l9CAeR VAKL7zKv/h/FMRPZE8GEvRgl6+ynO3ibnWiCea73VJFcBw6oWlNE7CK9D1lZRHsWsGl9vuuxHabndA KMjRp54Y3Q1+41KoEqBLVyOgDDDiJsIkdBdwUfp4qkAExnD5gUCww5IVi8kuSbxgVfQE0+fPGLP5CP 42RLDahpjj4OrtB14PISLIzEXWKEMzuBpAyER4wJxPm+NK1F+FqExFzHO2g9qfdnvL4LIqEYbtIjfZ gW8eaYTWWBvykRtuqn0OPfSHczGGyAYuTglWXhN3rTuXQi3BIm9WAw4LJDgeNisyswL0y3/J3WhYXb cHmOCDzS6JGQMfvdq7ZncVI9He3DE5U/AXRrxeI9tC3lf7yb+GOSvd2UGJk08cvstRt+5Dbqujewhm UgtX2ZFldHEIo2TeQ5Y06PHH3z7ScNq1L7rZo3NDAL6zgMbGmOQaGl1ImS2gB1GERFxxgSeacvuOzt L6NW1KGxsNKAmmO1S72Zg/Q7Kcj0g1kA2PJSye9mp9OOsQmVCvA9Gl+dSOkg== X-Developer-Key: i=louis.chauvet@bootlin.com; a=openpgp; fpr=8B7104AE9A272D6693F527F2EC1883F55E0B40A5 X-GND-Sasl: louis.chauvet@bootlin.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Introduce two callbacks which does nothing. They are used in replacement of NULL and it avoid kernel OOPS if this NULL is called. If those callback are used, it means that there is a mismatch between what formats are announced by atomic_check and what is realy supported by atomic_update. Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_formats.c | 42 +++++++++++++++++++++++++++++++------ 1 file changed, 36 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_formats.c b/drivers/gpu/drm/vkms/vkms_formats.c index 393c73caad72..29ca403827a6 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.c +++ b/drivers/gpu/drm/vkms/vkms_formats.c @@ -136,6 +136,21 @@ static void RGB565_to_argb_u16(u8 *in_pixel, struct pixel_argb_u16 *out_pixel) out_pixel->b = drm_fixp2int_round(drm_fixp_mul(fp_b, fp_rb_ratio)); } +/** + * black_to_argb_u16() - pixel_read callback which always read black + * + * This callback is used when an invalid format is requested for plane reading. + * It is used to avoid null pointer to be used as a function. In theory, this function should + * never be called, except if you found a bug in the driver/DRM core. + */ +static void black_to_argb_u16(u8 *in_pixel, struct pixel_argb_u16 *out_pixel) +{ + out_pixel->a = (u16) 0xFFFF; + out_pixel->r = 0; + out_pixel->g = 0; + out_pixel->b = 0; +} + /** * vkms_compose_row - compose a single row of a plane * @stage_buffer: output line with the composed pixels @@ -238,6 +253,15 @@ static void argb_u16_to_RGB565(u8 *out_pixel, struct pixel_argb_u16 *in_pixel) *pixel = cpu_to_le16(r << 11 | g << 5 | b); } +/** + * argb_u16_to_nothing() - pixel_write callback with no effect + * + * This callback is used when an invalid format is requested for writeback. + * It is used to avoid null pointer to be used as a function. In theory, this should never + * happen, except if there is a bug in the driver + */ +static void argb_u16_to_nothing(u8 *out_pixel, struct pixel_argb_u16 *in_pixel) {} + /** * Generic loop for all supported writeback format. It is executed just after the blending to * write a line in the writeback buffer. @@ -261,8 +285,8 @@ void vkms_writeback_row(struct vkms_writeback_job *wb, /** * Retrieve the correct read_pixel function for a specific format. - * The returned pointer is NULL for unsupported pixel formats. The caller must ensure that the - * pointer is valid before using it in a vkms_plane_state. + * If the format is not supported by VKMS a warn is emitted and a dummy "always read black" + * function is returned. * * @format: DRM_FORMAT_* value for which to obtain a conversion function (see [drm_fourcc.h]) */ @@ -285,17 +309,20 @@ pixel_read_t get_pixel_read_function(u32 format) * format must: * - Be listed in vkms_formats in vkms_plane.c * - Have a pixel_read callback defined here + * + * To avoid kernel crash, a dummy "always read black" function is used. It means + * that during the composition, this plane will always be black. */ WARN(true, "Pixel format %4cc is not supported by VKMS planes. This is a kernel bug, atomic check must forbid this configuration.\n", format); - return (pixel_read_t)NULL; + return &black_to_argb_u16; } } /** * Retrieve the correct write_pixel function for a specific format. - * The returned pointer is NULL for unsupported pixel formats. The caller must ensure that the - * pointer is valid before using it in a vkms_writeback_job. + * If the format is not supported by VKMS a warn is emitted and a dummy "don't do anything" + * function is returned. * * @format: DRM_FORMAT_* value for which to obtain a conversion function (see [drm_fourcc.h]) */ @@ -318,9 +345,12 @@ pixel_write_t get_pixel_write_function(u32 format) * format must: * - Be listed in vkms_wb_formats in vkms_writeback.c * - Have a pixel_write callback defined here + * + * To avoid kernel crash, a dummy "don't do anything" function is used. It means + * that the resulting writeback buffer is not composed and can contains any values. */ WARN(true, "Pixel format %4cc is not supported by VKMS writeback. This is a kernel bug, atomic check must forbid this configuration.\n", format); - return (pixel_write_t)NULL; + return &argb_u16_to_nothing; } } From patchwork Mon Mar 4 15:28:11 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Louis Chauvet X-Patchwork-Id: 13580737 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id EFD9BC48BF6 for ; Mon, 4 Mar 2024 15:29:30 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 8AE38112269; Mon, 4 Mar 2024 15:29:29 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=bootlin.com header.i=@bootlin.com header.b="dd5FbhFL"; dkim-atps=neutral Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) by gabe.freedesktop.org (Postfix) with ESMTPS id 015C81122A4 for ; Mon, 4 Mar 2024 15:29:26 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id D4D331C0010; Mon, 4 Mar 2024 15:29:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1709566165; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=o8LUKE39JY8ybFzAarIS0+XJ1i/6qp7K6c1tfJGj9bQ=; b=dd5FbhFLRLQ7axrQhbGNSEMBkq5MXNW8e1uruKOLYvti9LAIq/hoohuf/av23tiLJpMNfw SiCxph5fP7pLt+LB1kfx4Qa5dkHFHHEGpdJPtaTz83AnmGlfs7rq5grJ+s1fRbyJTF+CB9 2VkkxSb7BgBOD/aaBGWiNeF+JOh99wLIKqd0HoYFC4nwS5LZ1iOKOYSRTslX7gSOgrLPwO FehStUk6G2zY7d0qHj5qRzsISZavUD04UgD5SmGQnJwZY2jzML/3PuSuu76WFsxySBTk1v mXtZIpuLf7J7m2ZvBbtjgx9n+JPZ/WtIqHciZX+J+ysMxhBeqO71SxDjiXi+2Q== From: Louis Chauvet Date: Mon, 04 Mar 2024 16:28:11 +0100 Subject: [PATCH v4 06/14] drm/vkms: Use const for input pointers in pixel_read an pixel_write functions MIME-Version: 1.0 Message-Id: <20240304-yuv-v4-6-76beac8e9793@bootlin.com> References: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> In-Reply-To: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> To: Rodrigo Siqueira , Melissa Wen , =?utf-8?q?Ma=C3=ADra_Canal?= , Haneen Mohammed , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , arthurgrillo@riseup.net, Jonathan Corbet , pekka.paalanen@haloniitty.fi Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, jeremie.dautheribes@bootlin.com, miquel.raynal@bootlin.com, thomas.petazzoni@bootlin.com, seanpaul@google.com, marcheu@google.com, nicolejadeyee@google.com, Louis Chauvet X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=6527; i=louis.chauvet@bootlin.com; h=from:subject:message-id; bh=RPVRKA6Ba/aNHCg5fMJ52I7hctRCp4EyDzZTrh21ka8=; b=owEBbQKS/ZANAwAIASCtLsZbECziAcsmYgBl5ejLqEEj4SY8FKiG/XIazDNIccXcIOWAXNXsHj5w 0/8CgCiJAjMEAAEIAB0WIQRPj7g/vng8MQxQWQQgrS7GWxAs4gUCZeXoywAKCRAgrS7GWxAs4ttZEA DCFYY9VMGlPzws0CtRgDhUitW/LK8mhU8ZnbBgLLuTCAG4+pXQvMvMtSJc7gU2zpYmbhoWwUWcePQl kO4EimwSNR1YNVG0JWkgRqZ4IBg072A6Ew04C/fa3jcHRDL9nyL/k7JXTx81jE8PDC5nR0HPKY5uK5 T7WDQpgCjZUXJG2u9+GZ7QWwYPaSaBk6bO/skLux4KixIjiBafZSTXHgpKB60DMffPUyNpheuoFRuR jZWGVZy3yn8FMGc8rM4hVCqiAqkOASny9n0rfrLPzZ3n24EQgGfaSdic9UA3T8iA9/ZYokFCn/hg7S QGHSifHS258J19v0of2AOnDtqk83e60lsIhjyTCYx9RctdI2521ctjcIEPswjKc045IxZYoIFuCrof entFYOOsOPVjuNtg3N988FBSMOEgMcnWzoPjELzfEqLvqac7RIfR2gcaersHkcOb8/F+nZ5Ro/aXCF ANvKoi0n2GaSc7oPU4nxmqOzxY0a4WLQlOIPQayp3ODCTbHwblMdgD7qkS0vrxgpAUJTX7mCS70LFj X2h1cagcvk3fmN3ohN07UMQBz1r9SkzxxiDg0v4dlnO5ZOrx8+IjwILHjRvD1ltIZdUNg1t9RbAsT+ ocjnD9Asv/DVaESZLO/G3j3GHqlHg0p0tRtH1aQhecIBvNs5ZfbcYJLYKprw== X-Developer-Key: i=louis.chauvet@bootlin.com; a=openpgp; fpr=8B7104AE9A272D6693F527F2EC1883F55E0B40A5 X-GND-Sasl: louis.chauvet@bootlin.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" As the pixel_read and pixel_write function should never modify the input buffer, mark those pointers const. Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_drv.h | 4 ++-- drivers/gpu/drm/vkms/vkms_formats.c | 24 ++++++++++++------------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 4bfc62d26f08..3ead8b39af4a 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -61,7 +61,7 @@ struct line_buffer { * @out_pixel: destination address to write the pixel * @in_pixel: pixel to write */ -typedef void (*pixel_write_t)(u8 *out_pixel, struct pixel_argb_u16 *in_pixel); +typedef void (*pixel_write_t)(u8 *out_pixel, const struct pixel_argb_u16 *in_pixel); struct vkms_writeback_job { struct iosys_map data[DRM_FORMAT_MAX_PLANES]; @@ -76,7 +76,7 @@ struct vkms_writeback_job { * @in_pixel: Pointer to the pixel to read * @out_pixel: Pointer to write the converted pixel */ -typedef void (*pixel_read_t)(u8 *in_pixel, struct pixel_argb_u16 *out_pixel); +typedef void (*pixel_read_t)(const u8 *in_pixel, struct pixel_argb_u16 *out_pixel); /** * vkms_plane_state - Driver specific plane state diff --git a/drivers/gpu/drm/vkms/vkms_formats.c b/drivers/gpu/drm/vkms/vkms_formats.c index 29ca403827a6..bdd15964ce24 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.c +++ b/drivers/gpu/drm/vkms/vkms_formats.c @@ -76,7 +76,7 @@ static int get_x_position(const struct vkms_frame_info *frame_info, int limit, i * They are used in the `vkms_compose_row` function to handle multiple formats. */ -static void ARGB8888_to_argb_u16(u8 *in_pixel, struct pixel_argb_u16 *out_pixel) +static void ARGB8888_to_argb_u16(const u8 *in_pixel, struct pixel_argb_u16 *out_pixel) { /* * The 257 is the "conversion ratio". This number is obtained by the @@ -90,7 +90,7 @@ static void ARGB8888_to_argb_u16(u8 *in_pixel, struct pixel_argb_u16 *out_pixel) out_pixel->b = (u16)in_pixel[0] * 257; } -static void XRGB8888_to_argb_u16(u8 *in_pixel, struct pixel_argb_u16 *out_pixel) +static void XRGB8888_to_argb_u16(const u8 *in_pixel, struct pixel_argb_u16 *out_pixel) { out_pixel->a = (u16)0xffff; out_pixel->r = (u16)in_pixel[2] * 257; @@ -98,7 +98,7 @@ static void XRGB8888_to_argb_u16(u8 *in_pixel, struct pixel_argb_u16 *out_pixel) out_pixel->b = (u16)in_pixel[0] * 257; } -static void ARGB16161616_to_argb_u16(u8 *in_pixel, struct pixel_argb_u16 *out_pixel) +static void ARGB16161616_to_argb_u16(const u8 *in_pixel, struct pixel_argb_u16 *out_pixel) { u16 *pixel = (u16 *)in_pixel; @@ -108,7 +108,7 @@ static void ARGB16161616_to_argb_u16(u8 *in_pixel, struct pixel_argb_u16 *out_pi out_pixel->b = le16_to_cpu(pixel[0]); } -static void XRGB16161616_to_argb_u16(u8 *in_pixel, struct pixel_argb_u16 *out_pixel) +static void XRGB16161616_to_argb_u16(const u8 *in_pixel, struct pixel_argb_u16 *out_pixel) { u16 *pixel = (u16 *)in_pixel; @@ -118,7 +118,7 @@ static void XRGB16161616_to_argb_u16(u8 *in_pixel, struct pixel_argb_u16 *out_pi out_pixel->b = le16_to_cpu(pixel[0]); } -static void RGB565_to_argb_u16(u8 *in_pixel, struct pixel_argb_u16 *out_pixel) +static void RGB565_to_argb_u16(const u8 *in_pixel, struct pixel_argb_u16 *out_pixel) { u16 *pixel = (u16 *)in_pixel; @@ -143,7 +143,7 @@ static void RGB565_to_argb_u16(u8 *in_pixel, struct pixel_argb_u16 *out_pixel) * It is used to avoid null pointer to be used as a function. In theory, this function should * never be called, except if you found a bug in the driver/DRM core. */ -static void black_to_argb_u16(u8 *in_pixel, struct pixel_argb_u16 *out_pixel) +static void black_to_argb_u16(const u8 *in_pixel, struct pixel_argb_u16 *out_pixel) { out_pixel->a = (u16) 0xFFFF; out_pixel->r = 0; @@ -189,7 +189,7 @@ void vkms_compose_row(struct line_buffer *stage_buffer, struct vkms_plane_state * They are used in the `vkms_writeback_row` to convert and store a pixel from the src_buffer to * the writeback buffer. */ -static void argb_u16_to_ARGB8888(u8 *out_pixel, struct pixel_argb_u16 *in_pixel) +static void argb_u16_to_ARGB8888(u8 *out_pixel, const struct pixel_argb_u16 *in_pixel) { /* * This sequence below is important because the format's byte order is @@ -207,7 +207,7 @@ static void argb_u16_to_ARGB8888(u8 *out_pixel, struct pixel_argb_u16 *in_pixel) out_pixel[0] = DIV_ROUND_CLOSEST(in_pixel->b, 257); } -static void argb_u16_to_XRGB8888(u8 *out_pixel, struct pixel_argb_u16 *in_pixel) +static void argb_u16_to_XRGB8888(u8 *out_pixel, const struct pixel_argb_u16 *in_pixel) { out_pixel[3] = 0xff; out_pixel[2] = DIV_ROUND_CLOSEST(in_pixel->r, 257); @@ -215,7 +215,7 @@ static void argb_u16_to_XRGB8888(u8 *out_pixel, struct pixel_argb_u16 *in_pixel) out_pixel[0] = DIV_ROUND_CLOSEST(in_pixel->b, 257); } -static void argb_u16_to_ARGB16161616(u8 *out_pixel, struct pixel_argb_u16 *in_pixel) +static void argb_u16_to_ARGB16161616(u8 *out_pixel, const struct pixel_argb_u16 *in_pixel) { u16 *pixel = (u16 *)out_pixel; @@ -225,7 +225,7 @@ static void argb_u16_to_ARGB16161616(u8 *out_pixel, struct pixel_argb_u16 *in_pi pixel[0] = cpu_to_le16(in_pixel->b); } -static void argb_u16_to_XRGB16161616(u8 *out_pixel, struct pixel_argb_u16 *in_pixel) +static void argb_u16_to_XRGB16161616(u8 *out_pixel, const struct pixel_argb_u16 *in_pixel) { u16 *pixel = (u16 *)out_pixel; @@ -235,7 +235,7 @@ static void argb_u16_to_XRGB16161616(u8 *out_pixel, struct pixel_argb_u16 *in_pi pixel[0] = cpu_to_le16(in_pixel->b); } -static void argb_u16_to_RGB565(u8 *out_pixel, struct pixel_argb_u16 *in_pixel) +static void argb_u16_to_RGB565(u8 *out_pixel, const struct pixel_argb_u16 *in_pixel) { u16 *pixel = (u16 *)out_pixel; @@ -260,7 +260,7 @@ static void argb_u16_to_RGB565(u8 *out_pixel, struct pixel_argb_u16 *in_pixel) * It is used to avoid null pointer to be used as a function. In theory, this should never * happen, except if there is a bug in the driver */ -static void argb_u16_to_nothing(u8 *out_pixel, struct pixel_argb_u16 *in_pixel) {} +static void argb_u16_to_nothing(u8 *out_pixel, const struct pixel_argb_u16 *in_pixel) {} /** * Generic loop for all supported writeback format. It is executed just after the blending to From patchwork Mon Mar 4 15:28:12 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Louis Chauvet X-Patchwork-Id: 13580739 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E5B51C54E4A for ; Mon, 4 Mar 2024 15:29:32 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id ACA701122A3; Mon, 4 Mar 2024 15:29:30 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=bootlin.com header.i=@bootlin.com header.b="SGnKRm17"; dkim-atps=neutral Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) by gabe.freedesktop.org (Postfix) with ESMTPS id 4B36311228A for ; Mon, 4 Mar 2024 15:29:28 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id DD57E1C0005; Mon, 4 Mar 2024 15:29:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1709566166; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tkMA90xZNbAtS5RoA+EDPhLYGxyx6rZctamxCUhrcic=; b=SGnKRm17Zx46uCAKdiTDmu/qAN/XtL96BcTrAC1bWB7ZnvOBwmKWs1MZz2QPJcMLknjJMh 36o46HveSFxrg3CJl2FVwp3K5Aicl0s4kQqEtbeaVlvr4xwOJnEugokcBdiPCsXfsBQRvW 7vwAUJT7RXVCGzjJCbdTo+enZXXo05+2OY3bSHK2ANQc9a9hZ5t90DA5QxUhxCwlEm/m86 8pIWv8GQJ+zsL4hwu0KYAz+SOoqqGX/VDs4KcjSrQ5Hk8whMfCAAanhhtYKfCY2YXoCcM6 5RgZ/UJy9+9NUD4V1w+yQTwWY6ehW8UkRVlIDdUa44enrZEKkmXuQFedT0x3+w== From: Louis Chauvet Date: Mon, 04 Mar 2024 16:28:12 +0100 Subject: [PATCH v4 07/14] drm/vkms: Update pixels accessor to support packed and multi-plane formats. MIME-Version: 1.0 Message-Id: <20240304-yuv-v4-7-76beac8e9793@bootlin.com> References: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> In-Reply-To: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> To: Rodrigo Siqueira , Melissa Wen , =?utf-8?q?Ma=C3=ADra_Canal?= , Haneen Mohammed , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , arthurgrillo@riseup.net, Jonathan Corbet , pekka.paalanen@haloniitty.fi Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, jeremie.dautheribes@bootlin.com, miquel.raynal@bootlin.com, thomas.petazzoni@bootlin.com, seanpaul@google.com, marcheu@google.com, nicolejadeyee@google.com, Louis Chauvet X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=6343; i=louis.chauvet@bootlin.com; h=from:subject:message-id; bh=JIoXrYSBgeg0QLNIPh8bxgpI6Eagu1fkt6Zjo95AAXg=; b=owEBbQKS/ZANAwAIASCtLsZbECziAcsmYgBl5ejLB5olR9HyMbIVafJg3K0bne07ZtxNWsInxYTw m3vcOXWJAjMEAAEIAB0WIQRPj7g/vng8MQxQWQQgrS7GWxAs4gUCZeXoywAKCRAgrS7GWxAs4qKkD/ 9uf7hPdWfm5uXVdtNAAm/Bml6Jt6c7eKPIqp0WVrbVRfu9v2xKRE0pAJTzj+ZcmyNfPcPbp89b8Wly 5eQNEXrjxhaIHFm2dgTOw6cOX5hLtWhhpLs6tYxpF6Lu9WXmpUhYDJVWqj9xwtgrrkLZ2jmQmSQjxS +eUyFtKGrMdN1BuCw3Dw2Hz4llqIny8G7McEVmcNspkvM/jwY3j77jm5zSO1JZ4kI/jtTFLOTmC3D4 oRSWZ6G92hKalEh1XHHrWlsAF0x0335u7q1cU61YZHURZuP+VIXPMtP2DT98DnlSk1RGUUeW64SGkt wOW0f79Ka4sg0xHFcrg3Nz3hULmSCQ5Nf4wUYp/zJ03Y+8JeEDcwh/2oyjE+4xnNl4JXhjan1JvSnZ J3dXLDLW6LDTBtRtappU5swFvgOsXtJQAQPS0JOxeSB2ZeVK1hgITV08YNA/dQz2gFbcg2Uk0bKaCU MLMQkOTJaNQJo0pJRCT0H4WYYSoKY7bOi5OFqgftXg6sf2JvM+hWk7Qr4ZkO5LAQpl0LzzHLcU1Qif YRPrfME2K5OT+pjHGOmin0As6MxALomwJFKod5WloVRoLWg2CLZxuQfimfoX7GPHT6fyyNItNmtS0K RItClVkD503P6MG9s+X1yGfGsWpXHE5Lc9W6COs9kjhbOTlGBb6a6LNyoSug== X-Developer-Key: i=louis.chauvet@bootlin.com; a=openpgp; fpr=8B7104AE9A272D6693F527F2EC1883F55E0B40A5 X-GND-Sasl: louis.chauvet@bootlin.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Introduce the usage of block_h/block_w to compute the offset and the pointer of a pixel. The previous implementation was specialized for planes with block_h == block_w == 1. To avoid confusion and allow easier implementation of tiled formats. It also remove the usage of the deprecated format field `cpp`. Introduce the plane_index parameter to get an offset/pointer on a different plane. Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_formats.c | 59 +++++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 25 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_formats.c b/drivers/gpu/drm/vkms/vkms_formats.c index bdd15964ce24..089e4bdd5da8 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.c +++ b/drivers/gpu/drm/vkms/vkms_formats.c @@ -10,23 +10,33 @@ #include "vkms_formats.h" /** - * pixel_offset() - Get the offset of the pixel at coordinates x/y in the first plane + * packed_pixels_offset() - Get the offset of the block containing the pixel at coordinates x/y * * @frame_info: Buffer metadata * @x: The x coordinate of the wanted pixel in the buffer * @y: The y coordinate of the wanted pixel in the buffer + * @plane_index: The index of the plane to use * - * The caller must ensure that the framebuffer associated with this request uses a pixel format - * where block_h == block_w == 1. - * If this requirement is not fulfilled, the resulting offset can point to an other pixel or - * outside of the buffer. + * The returned offset correspond to the offset of the block containing the pixel at coordinates + * x/y. + * The caller must use this offset with care, as for formats with block_h != 1 or block_w != 1 + * the requested pixel value may have to be extracted from the block, even if they are + * individually addressable. */ -static size_t pixel_offset(const struct vkms_frame_info *frame_info, int x, int y) +static size_t packed_pixels_offset(const struct vkms_frame_info *frame_info, int x, int y, + size_t plane_index) { struct drm_framebuffer *fb = frame_info->fb; - - return fb->offsets[0] + (y * fb->pitches[0]) - + (x * fb->format->cpp[0]); + const struct drm_format_info *format = frame_info->fb->format; + /* Directly using x and y to multiply pitches and format->ccp is not sufficient because + * in some formats a block can represent multiple pixels. + * + * Dividing x and y by the block size allows to extract the correct offset of the block + * containing the pixel. + */ + return fb->offsets[plane_index] + + (y / drm_format_info_block_width(format, plane_index)) * fb->pitches[plane_index] + + (x / drm_format_info_block_height(format, plane_index)) * format->char_per_block[plane_index]; } /** @@ -36,30 +46,29 @@ static size_t pixel_offset(const struct vkms_frame_info *frame_info, int x, int * @frame_info: Buffer metadata * @x: The x(width) coordinate inside the plane * @y: The y(height) coordinate inside the plane + * @plane_index: The index of the plane * - * Takes the information stored in the frame_info, a pair of coordinates, and - * returns the address of the first color channel. - * This function assumes the channels are packed together, i.e. a color channel - * comes immediately after another in the memory. And therefore, this function - * doesn't work for YUV with chroma subsampling (e.g. YUV420 and NV21). + * Takes the information stored in the frame_info, a pair of coordinates, and returns the address + * of the block containing this pixel. * - * The caller must ensure that the framebuffer associated with this request uses a pixel format - * where block_h == block_w == 1, otherwise the returned pointer can be outside the buffer. + * The returned pointer points to the block containing the pixel at coordinates x/y. + * The caller must use this pointer with care, as for formats with block_h != 1 or block_w != 1 + * the requested pixel may have to be extracted from the block, even if they are + * individually addressable. */ static void *packed_pixels_addr(const struct vkms_frame_info *frame_info, - int x, int y) + int x, int y, size_t plane_index) { - size_t offset = pixel_offset(frame_info, x, y); - - return (u8 *)frame_info->map[0].vaddr + offset; + return (u8 *)frame_info->map[0].vaddr + packed_pixels_offset(frame_info, x, y, plane_index); } -static void *get_packed_src_addr(const struct vkms_frame_info *frame_info, int y) +static void *get_packed_src_addr(const struct vkms_frame_info *frame_info, int y, + size_t plane_index) { int x_src = frame_info->src.x1 >> 16; int y_src = y - frame_info->rotated.y1 + (frame_info->src.y1 >> 16); - return packed_pixels_addr(frame_info, x_src, y_src); + return packed_pixels_addr(frame_info, x_src, y_src, plane_index); } static int get_x_position(const struct vkms_frame_info *frame_info, int limit, int x) @@ -168,14 +177,14 @@ void vkms_compose_row(struct line_buffer *stage_buffer, struct vkms_plane_state { struct pixel_argb_u16 *out_pixels = stage_buffer->pixels; struct vkms_frame_info *frame_info = plane->frame_info; - u8 *src_pixels = get_packed_src_addr(frame_info, y); + u8 *src_pixels = get_packed_src_addr(frame_info, y, 0); int limit = min_t(size_t, drm_rect_width(&frame_info->dst), stage_buffer->n_pixels); for (size_t x = 0; x < limit; x++, src_pixels += frame_info->fb->format->cpp[0]) { int x_pos = get_x_position(frame_info, limit, x); if (drm_rotation_90_or_270(frame_info->rotation)) - src_pixels = get_packed_src_addr(frame_info, x + frame_info->rotated.y1) + src_pixels = get_packed_src_addr(frame_info, x + frame_info->rotated.y1, 0) + frame_info->fb->format->cpp[0] * y; plane->pixel_read(src_pixels, &out_pixels[x_pos]); @@ -275,7 +284,7 @@ void vkms_writeback_row(struct vkms_writeback_job *wb, { struct vkms_frame_info *frame_info = &wb->wb_frame_info; int x_dst = frame_info->dst.x1; - u8 *dst_pixels = packed_pixels_addr(frame_info, x_dst, y); + u8 *dst_pixels = packed_pixels_addr(frame_info, x_dst, y, 0); struct pixel_argb_u16 *in_pixels = src_buffer->pixels; int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), src_buffer->n_pixels); From patchwork Mon Mar 4 15:28:13 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Louis Chauvet X-Patchwork-Id: 13580740 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 408BEC5478C for ; Mon, 4 Mar 2024 15:29:34 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 00EC411228F; Mon, 4 Mar 2024 15:29:32 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=bootlin.com header.i=@bootlin.com header.b="V340mM9e"; dkim-atps=neutral Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) by gabe.freedesktop.org (Postfix) with ESMTPS id 4CFB711205E for ; Mon, 4 Mar 2024 15:29:29 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id 00B5B1C000E; Mon, 4 Mar 2024 15:29:26 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1709566167; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=zlPJwPnunQbGidl7fHxGe4JYFmFSn93i4z+wR+eCxZY=; b=V340mM9ebh4hDSnmayeSxNSglNxrj1f5u7xvWPsVXFvoxE/xLBpYmUMQJZL0aFf5vneJ24 yhD5vU/Cw2APf+1txmZrYf1fkVbTSWV9//srZfnBcHaMXQnU9GQ7CpVvpL6n2FgUri4HNp 33eFgKOnMQYBwW/oSJk8b/LyzWh5VvayU0oVBua344OHJPD87gtXqyy/DvDmwrBicRXD50 WYa3Rx20XelYV2/HIwZAfjKoTBhbIEmgaBSClhI8OYQvN3Glq/3qAMerauXnKHTsiAD5GI N5sIiPCXWcY1puh7oBonIS1w0VussWxywP0kFEXNti6ejhwi1Z59sU7LjaevWA== From: Louis Chauvet Date: Mon, 04 Mar 2024 16:28:13 +0100 Subject: [PATCH v4 08/14] drm/vkms: Avoid computing blending limits inside pre_mul_alpha_blend MIME-Version: 1.0 Message-Id: <20240304-yuv-v4-8-76beac8e9793@bootlin.com> References: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> In-Reply-To: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> To: Rodrigo Siqueira , Melissa Wen , =?utf-8?q?Ma=C3=ADra_Canal?= , Haneen Mohammed , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , arthurgrillo@riseup.net, Jonathan Corbet , pekka.paalanen@haloniitty.fi Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, jeremie.dautheribes@bootlin.com, miquel.raynal@bootlin.com, thomas.petazzoni@bootlin.com, seanpaul@google.com, marcheu@google.com, nicolejadeyee@google.com, Louis Chauvet X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=4025; i=louis.chauvet@bootlin.com; h=from:subject:message-id; bh=XzAcWcn+2gPTC+2NmrNB0BrJq5y1708nNfvcdGRsxyM=; b=owEBbQKS/ZANAwAIASCtLsZbECziAcsmYgBl5ejMEigVnIk7GZaM3RDJKUfZuS41fLYX6FeURKUO wUlMk2CJAjMEAAEIAB0WIQRPj7g/vng8MQxQWQQgrS7GWxAs4gUCZeXozAAKCRAgrS7GWxAs4ky1EA CEw8nxLowl2vjtUYcf3BR0As9SZjqf6gU9aVS6z+SF48UKqM09GPw8ZgIUtr0GbcVZH/KxrEb4ckj2 N5WxU08kkYxkEvYUOyQ/xziP/fi4RJsGPf/o2F/HGP7fWs98UcsF0BvQ63jDgbASvuEY9Oyc9ZjN3/ eW650EorgyZilJ+u/qAfDbTEVDL3oUw11Ty1gdAYldTMSKoaANy/40mC0gEJvjBWwDTzKpZwmuR+SJ egiNxCpB7AOEUzupFMP4dSx6znT3t4G1tnRZPL+V2BfnurTaqx0R1QLFSj6mq+49U2ccYK2bAXDzcu JH/pkhatIZl9KfJSU8zW80MiNNuhLTvEpz1UwEXGw21RmJ7E8RQ+ReR2Kl7VYSruKfObGZsjds+JaJ 2bS0tH2rAesEu/PozDyqJTf49REwbh2I8G5NqgoSp7ewfVB9IMqSoPVwx8qRrE63ZE/J2z4V92lqmQ Il9mVFB7k2195HFZyKbc2L/xvtwigsWFslJnf6Ocmi9Qnr6OrgoyCIf12EarVOQEtNprRPjVUeXJWR O2MX/TQyePmkTXwvkBAY0P2tMvPtWybX1MemyBfLIY/k3CsxNZ/2ItW+1t6uDMC5s8J8rxySuPgC1K mknUrYsC2zPmHCCIj6GUq7PhstjYBfTCZnt9nLKaI9sQEhxCusFRVp9Efm9A== X-Developer-Key: i=louis.chauvet@bootlin.com; a=openpgp; fpr=8B7104AE9A272D6693F527F2EC1883F55E0B40A5 X-GND-Sasl: louis.chauvet@bootlin.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" The pre_mul_alpha_blend is dedicated to blending, so to avoid mixing different concepts (coordinate calculation and color management), extract the x_limit and x_dst computation outside of this helper. It also increases the maintainability by grouping the computation related to coordinates in the same place: the loop in `blend`. Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_composer.c | 43 ++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 21 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index da0651a94c9b..26e8789630bd 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -24,34 +24,33 @@ static u16 pre_mul_blend_channel(u16 src, u16 dst, u16 alpha) /** * pre_mul_alpha_blend - alpha blending equation - * @frame_info: Source framebuffer's metadata * @stage_buffer: The line with the pixels from src_plane * @output_buffer: A line buffer that receives all the blends output + * @x_start: The start offset to avoid useless copy + * @count: The number of byte to copy * - * Using the information from the `frame_info`, this blends only the - * necessary pixels from the `stage_buffer` to the `output_buffer` - * using premultiplied blend formula. + * Using @x_start and @count information, only few pixel can be blended instead of the whole line + * each time. * * The current DRM assumption is that pixel color values have been already * pre-multiplied with the alpha channel values. See more * drm_plane_create_blend_mode_property(). Also, this formula assumes a * completely opaque background. */ -static void pre_mul_alpha_blend(struct vkms_frame_info *frame_info, - struct line_buffer *stage_buffer, - struct line_buffer *output_buffer) +static void pre_mul_alpha_blend( + const struct line_buffer *stage_buffer, + struct line_buffer *output_buffer, + int x_start, + int pixel_count) { - int x_dst = frame_info->dst.x1; - struct pixel_argb_u16 *out = output_buffer->pixels + x_dst; - struct pixel_argb_u16 *in = stage_buffer->pixels; - int x_limit = min_t(size_t, drm_rect_width(&frame_info->dst), - stage_buffer->n_pixels); - - for (int x = 0; x < x_limit; x++) { - out[x].a = (u16)0xffff; - out[x].r = pre_mul_blend_channel(in[x].r, out[x].r, in[x].a); - out[x].g = pre_mul_blend_channel(in[x].g, out[x].g, in[x].a); - out[x].b = pre_mul_blend_channel(in[x].b, out[x].b, in[x].a); + struct pixel_argb_u16 *out = &output_buffer->pixels[x_start]; + const struct pixel_argb_u16 *in = &stage_buffer->pixels[x_start]; + + for (int i = 0; i < pixel_count; i++) { + out[i].a = (u16)0xffff; + out[i].r = pre_mul_blend_channel(in[i].r, out[i].r, in[i].a); + out[i].g = pre_mul_blend_channel(in[i].g, out[i].g, in[i].a); + out[i].b = pre_mul_blend_channel(in[i].b, out[i].b, in[i].a); } } @@ -183,7 +182,7 @@ static void blend(struct vkms_writeback_job *wb, { struct vkms_plane_state **plane = crtc_state->active_planes; u32 n_active_planes = crtc_state->num_active_planes; - int y_pos; + int y_pos, x_dst, x_limit; const struct pixel_argb_u16 background_color = { .a = 0xffff }; @@ -201,14 +200,16 @@ static void blend(struct vkms_writeback_job *wb, /* The active planes are composed associatively in z-order. */ for (size_t i = 0; i < n_active_planes; i++) { + x_dst = plane[i]->frame_info->dst.x1; + x_limit = min_t(size_t, drm_rect_width(&plane[i]->frame_info->dst), + stage_buffer->n_pixels); y_pos = get_y_pos(plane[i]->frame_info, y); if (!check_limit(plane[i]->frame_info, y_pos)) continue; vkms_compose_row(stage_buffer, plane[i], y_pos); - pre_mul_alpha_blend(plane[i]->frame_info, stage_buffer, - output_buffer); + pre_mul_alpha_blend(stage_buffer, output_buffer, x_dst, x_limit); } apply_lut(crtc_state, output_buffer); From patchwork Mon Mar 4 15:28:14 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Louis Chauvet X-Patchwork-Id: 13580741 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A0D70C54E55 for ; Mon, 4 Mar 2024 15:29:35 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 345E911205E; Mon, 4 Mar 2024 15:29:34 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=bootlin.com header.i=@bootlin.com header.b="Ts3VOVkU"; dkim-atps=neutral Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) by gabe.freedesktop.org (Postfix) with ESMTPS id 37E2711205E for ; Mon, 4 Mar 2024 15:29:30 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id 0817E1C0003; Mon, 4 Mar 2024 15:29:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1709566169; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=XRdBGBr45+6C8R4ecjWPrxY0eSUCRzxD4rOLgPsUrZg=; b=Ts3VOVkUvBT2z25vcHqG2r1yiaeucxrjBMmbe9Z9Pg+Asdc2YZP2m+wrCzR2CAl5/jZwlI v4Be/nB3hSqEe+Rkw5cRgNXGtSdG35obqZlpIzRpOEouNANr5CFp3sUzlzVb+jkgi7dIdY c8sNw7f04tHYAgmwWxrTC5kAADGelSb7NxloWExUV2888YX1Yvk38ZzQBin7un5pBRfBm4 M0cusFbMVTzD499YHJOlZdszZi+jGTxP3W5megq47+BzGAhEFNs+yhKer5st2Ksaohpt4n nVrx3bwvQLF1aSjMevixKrdoHBbbVWs796SdQz/15JyMFeS+YGcPxvbHOXFbGA== From: Louis Chauvet Date: Mon, 04 Mar 2024 16:28:14 +0100 Subject: [PATCH v4 09/14] drm/vkms: Introduce pixel_read_direction enum MIME-Version: 1.0 Message-Id: <20240304-yuv-v4-9-76beac8e9793@bootlin.com> References: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> In-Reply-To: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> To: Rodrigo Siqueira , Melissa Wen , =?utf-8?q?Ma=C3=ADra_Canal?= , Haneen Mohammed , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , arthurgrillo@riseup.net, Jonathan Corbet , pekka.paalanen@haloniitty.fi Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, jeremie.dautheribes@bootlin.com, miquel.raynal@bootlin.com, thomas.petazzoni@bootlin.com, seanpaul@google.com, marcheu@google.com, nicolejadeyee@google.com, Louis Chauvet X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=4675; i=louis.chauvet@bootlin.com; h=from:subject:message-id; bh=81s8pH+2KKpkPCCipJdtlkeM01WWiW3JBRoPFdnRHvI=; b=owEBbQKS/ZANAwAIASCtLsZbECziAcsmYgBl5ejMaeFjK7sgLEywSSRXA2Nl+d3nYAMK/eVwDRQO O8hXb8yJAjMEAAEIAB0WIQRPj7g/vng8MQxQWQQgrS7GWxAs4gUCZeXozAAKCRAgrS7GWxAs4qu5D/ 9nDsvT5miB45QS9wIkhJImLzpVOk+YCjkccQ/TYobQTr/CQ7dyypzDlyssNPB+dCapkKDqGxvGfw4W RoouuzpVscaXkOKTzSiECs3yPrqN82ERz7J5+EEqM9P51SzfFnKSsjKvrbVJUdJ/32B6oV2GOIm8VA DaTBHJrFDesbamhgHCewBgUrvDpfEqp9LvCfURswApVQbFUDIb65j3UOP0STmZQwhtc1I3UTTdEbhg BP5on9Z1icYbDNdyXAhCzJZm/yVjNIvN6drg0mEFK6JDvGo3ajNYng+/UCvqvonBhRMGke8bzX1LKO DTYjI31BYgw4UAzVe/li139MpzPftxaghVQyW8TuscsP8RwYG0QypVE8SFX6MXGL8DvSz0SF/8jRJu 1wBWIF8ZWgTH9zmpghRUpC0NTmnyTO6yLtcoh8OkI/cYLaUzmC0bndJadgRuSO4qQtVcQdPMRniAhJ lYA1PIdxiYZlKYJvV5favC6kwXQahT9rAjjrMYDV7ZIGBHTdnDmXZ4JsDDSaBQ981GKACfjY1p/H8k W5sDnNryQv9E3O23v+b2Kvqz+ZMVsXHlbPTP6MdblLrsr2Hx/vM5y7OBgxaAqVEUm9/Q8GDQifuK9t GZjqy8JizhPdHT6VjWLEn7gHYHa01zvTsuEo8Cz9/KvGwkoqbAHO/NcO6uvw== X-Developer-Key: i=louis.chauvet@bootlin.com; a=openpgp; fpr=8B7104AE9A272D6693F527F2EC1883F55E0B40A5 X-GND-Sasl: louis.chauvet@bootlin.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" The pixel_read_direction enum is useful to describe the reading direction in a plane. It avoids using the rotation property of DRM, which not practical to know the direction of reading. This patch also introduce two helpers, one to compute the pixel_read_direction from the DRM rotation property, and one to compute the step, in byte, between two successive pixel in a specific direction. Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_composer.c | 36 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/vkms/vkms_drv.h | 11 +++++++++++ drivers/gpu/drm/vkms/vkms_formats.c | 28 ++++++++++++++++++++++++++++ 3 files changed, 75 insertions(+) diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index 26e8789630bd..068b6d838d7a 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -162,6 +162,42 @@ static void apply_lut(const struct vkms_crtc_state *crtc_state, struct line_buff } } +/** + * direction_for_rotation() - Get the correct reading direction for a given rotation + * + * This function will use the @rotation setting of a source plane to compute the reading + * direction in this plane which correspond to a "left to right writing" in the CRTC. + * For example, if the buffer is reflected on X axis, the pixel must be read from right to left + * to be written from left to right on the CRTC. + * + * @rotation: Rotation to analyze. It correspond the field @frame_info.rotation. + */ +static enum pixel_read_direction direction_for_rotation(unsigned int rotation) +{ + if (rotation & DRM_MODE_ROTATE_0) { + if (rotation & DRM_MODE_REFLECT_X) + return READ_RIGHT_TO_LEFT; + else + return READ_LEFT_TO_RIGHT; + } else if (rotation & DRM_MODE_ROTATE_90) { + if (rotation & DRM_MODE_REFLECT_Y) + return READ_BOTTOM_TO_TOP; + else + return READ_TOP_TO_BOTTOM; + } else if (rotation & DRM_MODE_ROTATE_180) { + if (rotation & DRM_MODE_REFLECT_X) + return READ_LEFT_TO_RIGHT; + else + return READ_RIGHT_TO_LEFT; + } else if (rotation & DRM_MODE_ROTATE_270) { + if (rotation & DRM_MODE_REFLECT_Y) + return READ_TOP_TO_BOTTOM; + else + return READ_BOTTOM_TO_TOP; + } + return READ_LEFT_TO_RIGHT; +} + /** * blend - blend the pixels from all planes and compute crc * @wb: The writeback frame buffer metadata diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 3ead8b39af4a..985e7a92b7bc 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -69,6 +69,17 @@ struct vkms_writeback_job { pixel_write_t pixel_write; }; +/** + * enum pixel_read_direction - Enum used internaly by VKMS to represent a reading direction in a + * plane. + */ +enum pixel_read_direction { + READ_BOTTOM_TO_TOP, + READ_TOP_TO_BOTTOM, + READ_RIGHT_TO_LEFT, + READ_LEFT_TO_RIGHT +}; + /** * typedef pixel_read_t - These functions are used to read a pixel in the source frame, * convert it to `struct pixel_argb_u16` and write it to @out_pixel. diff --git a/drivers/gpu/drm/vkms/vkms_formats.c b/drivers/gpu/drm/vkms/vkms_formats.c index 089e4bdd5da8..7a1bc1d8651f 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.c +++ b/drivers/gpu/drm/vkms/vkms_formats.c @@ -62,6 +62,34 @@ static void *packed_pixels_addr(const struct vkms_frame_info *frame_info, return (u8 *)frame_info->map[0].vaddr + packed_pixels_offset(frame_info, x, y, plane_index); } +/** + * get_step_1x1() - Common helper to compute the correct step value between each pixel to read in a + * certain direction. + * This must be used only with format where blockh == blockw == 1. + * In the case when direction is not a valid pixel_read_direction, the returned step is 0, so you + * must not rely on this result to create a loop variant if the direction can be invalid. + * + * @fb: Framebuffer to iter on + * @direction: Direction of the reading + * @plane_index: Plane to get the step from + */ +static int get_step_1x1(struct drm_framebuffer *fb, enum pixel_read_direction direction, + int plane_index) +{ + switch (direction) { + case READ_LEFT_TO_RIGHT: + return fb->format->char_per_block[plane_index]; + case READ_RIGHT_TO_LEFT: + return -fb->format->char_per_block[plane_index]; + case READ_TOP_TO_BOTTOM: + return (int)fb->pitches[plane_index]; + case READ_BOTTOM_TO_TOP: + return -(int)fb->pitches[plane_index]; + } + + return 0; +} + static void *get_packed_src_addr(const struct vkms_frame_info *frame_info, int y, size_t plane_index) { From patchwork Mon Mar 4 15:28:15 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Louis Chauvet X-Patchwork-Id: 13580745 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 0D35CC48BF6 for ; Mon, 4 Mar 2024 15:29:39 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id EA6A31122A4; Mon, 4 Mar 2024 15:29:37 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=bootlin.com header.i=@bootlin.com header.b="JCkcFhxf"; dkim-atps=neutral Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) by gabe.freedesktop.org (Postfix) with ESMTPS id 6BA5D11205E for ; Mon, 4 Mar 2024 15:29:31 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id 1D4051C000C; Mon, 4 Mar 2024 15:29:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1709566170; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=ViuTbDrVmKIbmBOw7HUo+ZTNuU1SgGLpFS99SwhQrsM=; b=JCkcFhxffdORV84WtYMxb2GbXxCtmtVYaidU0sJKadc2VHKopTOICqsMAyzpqNLuBkazzE brL3vY1Imb1tIzhnTeDYt7klFCDcFWeH52LCWqHIp/a2e+aE5kb1QKPHTCj3SzGGteKA3a xV4vvFx+rr/345KecwdwFE7z1bCxZeEFTyNSiDnf3pKZhZroZySpmlOIJ9n3GjTEy20SB3 NYFRrNe4PKnFWIUFXa4CT7w7Z4jiKjYn5CDjAffV3o0MKR5ty3nV6DPQcIKUaEHoEg7ktM N+F24bDZoBk0RcUyWmITRm48QVpSe2D2DV8hUGAIRNBYe6648IzviFwpP15JgA== From: Louis Chauvet Date: Mon, 04 Mar 2024 16:28:15 +0100 Subject: [PATCH v4 10/14] drm/vkms: Re-introduce line-per-line composition algorithm MIME-Version: 1.0 Message-Id: <20240304-yuv-v4-10-76beac8e9793@bootlin.com> References: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> In-Reply-To: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> To: Rodrigo Siqueira , Melissa Wen , =?utf-8?q?Ma=C3=ADra_Canal?= , Haneen Mohammed , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , arthurgrillo@riseup.net, Jonathan Corbet , pekka.paalanen@haloniitty.fi Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, jeremie.dautheribes@bootlin.com, miquel.raynal@bootlin.com, thomas.petazzoni@bootlin.com, seanpaul@google.com, marcheu@google.com, nicolejadeyee@google.com, Louis Chauvet X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=26229; i=louis.chauvet@bootlin.com; h=from:subject:message-id; bh=y/uBgYeisBqlVkvVAsYBdVe5eI8RGMb3SKWshH7JFL8=; b=owEBbQKS/ZANAwAIASCtLsZbECziAcsmYgBl5ejM2m2xbQ+oXtQdh6DLO8sNDT4M/AuVcWHWBiLI SSKt73iJAjMEAAEIAB0WIQRPj7g/vng8MQxQWQQgrS7GWxAs4gUCZeXozAAKCRAgrS7GWxAs4kUPD/ 9pqF/LkWjf1aOGFIWpdqBq3XtVa7JvDBoaw35HC2TH8kn1DHikOtAFkgojsUTrkLDe38tpjPm3/FsM OeREcnGOWYJN7sFA2HGmxjJuoTqWIJgay2nlwRiMMYcUA+hdWe7EmRfPi8ylLPztcS1hpMhgXGHpG5 ErZ6nCZBV1Xg4u6u9b6uch+MNgiGCSXLviqllIgIGRlAj1P8AGuGUcASdeJApUtPrudlqN0avkzHbl AYWVToT4eNxK9urLPsUsQ/9Jx7L0jT7rSkoN9O8/QWL9JAIk8+3ewVU+nr2onBmjuavy4LnHo7Vx5n VjrNnYbQzSrZuieDxU5varZJFZ8bMfI5xxOK/dPOVTMPeHZ3G5zskltwH2iNKfPNP+txhO2gg1PtMg v+aI1iZ4TBQhsZGwHduKVWm4LUTRvmm3XFVelEMChhbIdqplJh8v/IuERTaCae1jg+EVx5Zl5DdCtq rTnVErZZMC3RmATyiWRzor+lFtrJBMpNApNo+b8bRK7IBymsAobej6CwdvRBxMmyQPrx/W3GuREiBH YfwYyfpCXMIz4sUPsCpEd4t8/6DBmCis1pTeTaLRUmiEqWXYWcudhEPWsp+cYxo7lRZNNMCI5AogsW a7r33MyQg7aFkSo1bywhCPvgA/cHnbCYnOyglTWw9t8TiLx0cG3d63wrPqQg== X-Developer-Key: i=louis.chauvet@bootlin.com; a=openpgp; fpr=8B7104AE9A272D6693F527F2EC1883F55E0B40A5 X-GND-Sasl: louis.chauvet@bootlin.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" Re-introduce a line-by-line composition algorithm for each pixel format. This allows more performance by not requiring an indirection per pixel read. This patch is focused on readability of the code. Line-by-line composition was introduced by [1] but rewritten back to pixel-by-pixel algorithm in [2]. At this time, nobody noticed the impact on performance, and it was merged. This patch is almost a revert of [2], but in addition efforts have been made to increase readability and maintainability of the rotation handling. The blend function is now divided in two parts: - Transformation of coordinates from the output referential to the source referential - Line conversion and blending Most of the complexity of the rotation management is avoided by using drm_rect_* helpers. The remaining complexity is around the clipping, to avoid reading/writing outside source/destination buffers. The pixel conversion is now done line-by-line, so the read_pixel_t was replaced with read_pixel_line_t callback. This way the indirection is only required once per line and per plane, instead of once per pixel and per plane. The read_line_t callbacks are very similar for most pixel format, but it is required to avoid performance impact. Some helpers were created to avoid code repetition: - get_step_1x1: get the step in byte to reach next pixel block in a certain direction - *_to_argb_u16: helpers to perform colors conversion. They should be inlined by the compiler, and they are used to avoid repetition between multiple variants of the same format (argb/xrgb and maybe in the future for formats like bgr formats). This new algorithm was tested with: - kms_plane (for color conversions) - kms_rotation_crc (for rotations of planes) - kms_cursor_crc (for translations of planes) The performance gain was mesured with: - kms_fb_stress [1]: commit 8ba1648567e2 ("drm: vkms: Refactor the plane composer to accept new formats") https://lore.kernel.org/all/20220905190811.25024-7-igormtorrente@gmail.com/ [2]: commit 322d716a3e8a ("drm/vkms: isolate pixel conversion functionality") https://lore.kernel.org/all/20230418130525.128733-2-mcanal@igalia.com/ Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_composer.c | 169 ++++++++++++++++++++------- drivers/gpu/drm/vkms/vkms_drv.h | 27 +++-- drivers/gpu/drm/vkms/vkms_formats.c | 218 +++++++++++++++++++++-------------- drivers/gpu/drm/vkms/vkms_formats.h | 2 +- drivers/gpu/drm/vkms/vkms_plane.c | 5 +- 5 files changed, 280 insertions(+), 141 deletions(-) diff --git a/drivers/gpu/drm/vkms/vkms_composer.c b/drivers/gpu/drm/vkms/vkms_composer.c index 068b6d838d7a..62122ade7d67 100644 --- a/drivers/gpu/drm/vkms/vkms_composer.c +++ b/drivers/gpu/drm/vkms/vkms_composer.c @@ -54,33 +54,6 @@ static void pre_mul_alpha_blend( } } -static int get_y_pos(struct vkms_frame_info *frame_info, int y) -{ - if (frame_info->rotation & DRM_MODE_REFLECT_Y) - return drm_rect_height(&frame_info->rotated) - y - 1; - - switch (frame_info->rotation & DRM_MODE_ROTATE_MASK) { - case DRM_MODE_ROTATE_90: - return frame_info->rotated.x2 - y - 1; - case DRM_MODE_ROTATE_270: - return y + frame_info->rotated.x1; - default: - return y; - } -} - -static bool check_limit(struct vkms_frame_info *frame_info, int pos) -{ - if (drm_rotation_90_or_270(frame_info->rotation)) { - if (pos >= 0 && pos < drm_rect_width(&frame_info->rotated)) - return true; - } else { - if (pos >= frame_info->rotated.y1 && pos < frame_info->rotated.y2) - return true; - } - - return false; -} static void fill_background(const struct pixel_argb_u16 *background_color, struct line_buffer *output_buffer) @@ -218,34 +191,150 @@ static void blend(struct vkms_writeback_job *wb, { struct vkms_plane_state **plane = crtc_state->active_planes; u32 n_active_planes = crtc_state->num_active_planes; - int y_pos, x_dst, x_limit; const struct pixel_argb_u16 background_color = { .a = 0xffff }; - size_t crtc_y_limit = crtc_state->base.crtc->mode.vdisplay; + int crtc_y_limit = crtc_state->base.crtc->mode.vdisplay; + int crtc_x_limit = crtc_state->base.crtc->mode.hdisplay; /* * The planes are composed line-by-line to avoid heavy memory usage. It is a necessary * complexity to avoid poor blending performance. * - * The function vkms_compose_row is used to read a line, pixel-by-pixel, into the staging - * buffer. + * The function pixel_read_line callback is used to read a line, using an efficient + * algorithm for a specific format, into the staging buffer. */ for (size_t y = 0; y < crtc_y_limit; y++) { fill_background(&background_color, output_buffer); /* The active planes are composed associatively in z-order. */ for (size_t i = 0; i < n_active_planes; i++) { - x_dst = plane[i]->frame_info->dst.x1; - x_limit = min_t(size_t, drm_rect_width(&plane[i]->frame_info->dst), - stage_buffer->n_pixels); - y_pos = get_y_pos(plane[i]->frame_info, y); + struct vkms_plane_state *current_plane = plane[i]; - if (!check_limit(plane[i]->frame_info, y_pos)) + /* Avoid rendering useless lines */ + if (y < current_plane->frame_info->dst.y1 || + y >= current_plane->frame_info->dst.y2) continue; - vkms_compose_row(stage_buffer, plane[i], y_pos); - pre_mul_alpha_blend(stage_buffer, output_buffer, x_dst, x_limit); + /* + * dst_line is the line to copy. The initial coordinates are inside the + * destination framebuffer, and then drm_rect_* helpers are used to + * compute the correct position into the source framebuffer. + */ + struct drm_rect dst_line = DRM_RECT_INIT( + current_plane->frame_info->dst.x1, y, + drm_rect_width(¤t_plane->frame_info->dst), 1); + struct drm_rect tmp_src; + + drm_rect_fp_to_int(&tmp_src, ¤t_plane->frame_info->src); + + /* + * [1]: Clamping src_line to the crtc_x_limit to avoid writing outside of + * the destination buffer + */ + dst_line.x1 = max_t(int, dst_line.x1, 0); + dst_line.x2 = min_t(int, dst_line.x2, crtc_x_limit); + /* The destination is completely outside of the crtc. */ + if (dst_line.x2 <= dst_line.x1) + continue; + + struct drm_rect src_line = dst_line; + + /* + * Transform the coordinate x/y from the crtc to coordinates into + * coordinates for the src buffer. + * + * - Cancel the offset of the dst buffer. + * - Invert the rotation. This assumes that + * dst = drm_rect_rotate(src, rotation) (dst and src have the + * same size, but can be rotated). + * - Apply the offset of the source rectangle to the coordinate. + */ + drm_rect_translate(&src_line, -current_plane->frame_info->dst.x1, + -current_plane->frame_info->dst.y1); + drm_rect_rotate_inv(&src_line, + drm_rect_width(&tmp_src), + drm_rect_height(&tmp_src), + current_plane->frame_info->rotation); + drm_rect_translate(&src_line, tmp_src.x1, tmp_src.y1); + + /* Get the correct reading direction in the source buffer. */ + + enum pixel_read_direction direction = + direction_for_rotation(current_plane->frame_info->rotation); + + int x_start = src_line.x1; + int y_start = src_line.y1; + int pixel_count; + /* [2]: Compute and clamp the number of pixel to read */ + if (direction == READ_LEFT_TO_RIGHT || direction == READ_RIGHT_TO_LEFT) { + /* + * In horizontal reading, the src_line width is the number of pixel + * to read + */ + pixel_count = drm_rect_width(&src_line); + if (x_start < 0) { + pixel_count += x_start; + x_start = 0; + } + if (x_start + pixel_count > current_plane->frame_info->fb->width) { + pixel_count = + (int)current_plane->frame_info->fb->width - x_start; + } + } else { + /* + * In vertical reading, the src_line height is the number of pixel + * to read + */ + pixel_count = drm_rect_height(&src_line); + if (y_start < 0) { + pixel_count += y_start; + y_start = 0; + } + if (y_start + pixel_count > current_plane->frame_info->fb->height) { + pixel_count = + (int)current_plane->frame_info->fb->width - y_start; + } + } + + if (pixel_count <= 0) { + /* Nothing to read, so avoid multiple function calls for nothing */ + continue; + } + + /* + * Modify the starting point to take in account the rotation + * + * src_line is the top-left corner, so when reading READ_RIGHT_TO_LEFT or + * READ_BOTTOM_TO_TOP, it must be changed to the top-right/bottom-left + * corner. + */ + if (direction == READ_RIGHT_TO_LEFT) { + // x_start is now the right point + x_start += pixel_count - 1; + } else if (direction == READ_BOTTOM_TO_TOP) { + // y_start is now the bottom point + y_start += pixel_count - 1; + } + + /* + * Perform the conversion and the blending + * + * Here we know that the read line (x_start, y_start, pixel_count) is + * inside the source buffer [2] and we don't write outside the stage + * buffer [1] + */ + current_plane->pixel_read_line( + current_plane, + x_start, + y_start, + direction, + pixel_count, + &stage_buffer->pixels[current_plane->frame_info->dst.x1]); + + pre_mul_alpha_blend(stage_buffer, output_buffer, + current_plane->frame_info->dst.x1, + pixel_count); } apply_lut(crtc_state, output_buffer); @@ -253,7 +342,7 @@ static void blend(struct vkms_writeback_job *wb, *crc32 = crc32_le(*crc32, (void *)output_buffer->pixels, row_size); if (wb) - vkms_writeback_row(wb, output_buffer, y_pos); + vkms_writeback_row(wb, output_buffer, y); } } @@ -264,7 +353,7 @@ static int check_format_funcs(struct vkms_crtc_state *crtc_state, u32 n_active_planes = crtc_state->num_active_planes; for (size_t i = 0; i < n_active_planes; i++) - if (!planes[i]->pixel_read) + if (!planes[i]->pixel_read_line) return -1; if (active_wb && !active_wb->pixel_write) diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 985e7a92b7bc..23e1d247468d 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -39,7 +39,6 @@ struct vkms_frame_info { struct drm_framebuffer *fb; struct drm_rect src, dst; - struct drm_rect rotated; struct iosys_map map[DRM_FORMAT_MAX_PLANES]; unsigned int rotation; }; @@ -80,26 +79,37 @@ enum pixel_read_direction { READ_LEFT_TO_RIGHT }; +struct vkms_plane_state; + /** - * typedef pixel_read_t - These functions are used to read a pixel in the source frame, + * typedef pixel_read_line_t - These functions are used to read a pixel line in the source frame, * convert it to `struct pixel_argb_u16` and write it to @out_pixel. * - * @in_pixel: Pointer to the pixel to read - * @out_pixel: Pointer to write the converted pixel + * @plane: Plane used as source for the pixel value + * @x_start: X (width) coordinate of the first pixel to copy. The caller must ensure that x_start + * is positive and smaller than @plane->frame_info->fb->width. + * @y_start: Y (width) coordinate of the first pixel to copy. The caller must ensure that y_start + * is positive and smaller than @plane->frame_info->fb->height. + * @direction: Direction to use for the copy, starting at @x_start/@y_start + * @count: Number of pixels to copy + * @out_pixel: Pointer where to write the pixel values. They will be written from @out_pixel[0] + * to @out_pixel[@count]. The caller must ensure that out_pixel have a length of at least @count. */ -typedef void (*pixel_read_t)(const u8 *in_pixel, struct pixel_argb_u16 *out_pixel); +typedef void (*pixel_read_line_t)(const struct vkms_plane_state *plane, int x_start, + int y_start, enum pixel_read_direction direction, int count, + struct pixel_argb_u16 out_pixel[]); /** * vkms_plane_state - Driver specific plane state * @base: base plane state * @frame_info: data required for composing computation - * @pixel_read: function to read a pixel in this plane. The creator of a vkms_plane_state must - * ensure that this pointer is valid + * @pixel_read_line: function to read a pixel line in this plane. The creator of a vkms_plane_state + * must ensure that this pointer is valid */ struct vkms_plane_state { struct drm_shadow_plane_state base; struct vkms_frame_info *frame_info; - pixel_read_t pixel_read; + pixel_read_line_t pixel_read_line; }; struct vkms_plane { @@ -204,7 +214,6 @@ int vkms_verify_crc_source(struct drm_crtc *crtc, const char *source_name, /* Composer Support */ void vkms_composer_worker(struct work_struct *work); void vkms_set_composer(struct vkms_output *out, bool enabled); -void vkms_compose_row(struct line_buffer *stage_buffer, struct vkms_plane_state *plane, int y); void vkms_writeback_row(struct vkms_writeback_job *wb, const struct line_buffer *src_buffer, int y); /* Writeback */ diff --git a/drivers/gpu/drm/vkms/vkms_formats.c b/drivers/gpu/drm/vkms/vkms_formats.c index 7a1bc1d8651f..87af3962ee12 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.c +++ b/drivers/gpu/drm/vkms/vkms_formats.c @@ -90,74 +90,45 @@ static int get_step_1x1(struct drm_framebuffer *fb, enum pixel_read_direction di return 0; } -static void *get_packed_src_addr(const struct vkms_frame_info *frame_info, int y, - size_t plane_index) -{ - int x_src = frame_info->src.x1 >> 16; - int y_src = y - frame_info->rotated.y1 + (frame_info->src.y1 >> 16); - - return packed_pixels_addr(frame_info, x_src, y_src, plane_index); -} - -static int get_x_position(const struct vkms_frame_info *frame_info, int limit, int x) -{ - if (frame_info->rotation & (DRM_MODE_REFLECT_X | DRM_MODE_ROTATE_270)) - return limit - x - 1; - return x; -} - /* - * The following functions take pixel data from the buffer and convert them to the format + * The following functions take pixel data (a, r, g, b, pixel, ...), convert them to the format * ARGB16161616 in out_pixel. * - * They are used in the `vkms_compose_row` function to handle multiple formats. + * They are used in the `read_line`s functions to avoid duplicate work for some pixel formats. */ -static void ARGB8888_to_argb_u16(const u8 *in_pixel, struct pixel_argb_u16 *out_pixel) +static struct pixel_argb_u16 argb_u16_from_u8888(int a, int r, int g, int b) { + struct pixel_argb_u16 out_pixel; /* * The 257 is the "conversion ratio". This number is obtained by the * (2^16 - 1) / (2^8 - 1) division. Which, in this case, tries to get * the best color value in a pixel format with more possibilities. * A similar idea applies to others RGB color conversions. */ - out_pixel->a = (u16)in_pixel[3] * 257; - out_pixel->r = (u16)in_pixel[2] * 257; - out_pixel->g = (u16)in_pixel[1] * 257; - out_pixel->b = (u16)in_pixel[0] * 257; -} + out_pixel.a = (u16)a * 257; + out_pixel.r = (u16)r * 257; + out_pixel.g = (u16)g * 257; + out_pixel.b = (u16)b * 257; -static void XRGB8888_to_argb_u16(const u8 *in_pixel, struct pixel_argb_u16 *out_pixel) -{ - out_pixel->a = (u16)0xffff; - out_pixel->r = (u16)in_pixel[2] * 257; - out_pixel->g = (u16)in_pixel[1] * 257; - out_pixel->b = (u16)in_pixel[0] * 257; + return out_pixel; } -static void ARGB16161616_to_argb_u16(const u8 *in_pixel, struct pixel_argb_u16 *out_pixel) +static struct pixel_argb_u16 argb_u16_from_u16161616(int a, int r, int g, int b) { - u16 *pixel = (u16 *)in_pixel; + struct pixel_argb_u16 out_pixel; - out_pixel->a = le16_to_cpu(pixel[3]); - out_pixel->r = le16_to_cpu(pixel[2]); - out_pixel->g = le16_to_cpu(pixel[1]); - out_pixel->b = le16_to_cpu(pixel[0]); -} - -static void XRGB16161616_to_argb_u16(const u8 *in_pixel, struct pixel_argb_u16 *out_pixel) -{ - u16 *pixel = (u16 *)in_pixel; + out_pixel.a = le16_to_cpu(a); + out_pixel.r = le16_to_cpu(r); + out_pixel.g = le16_to_cpu(g); + out_pixel.b = le16_to_cpu(b); - out_pixel->a = (u16)0xffff; - out_pixel->r = le16_to_cpu(pixel[2]); - out_pixel->g = le16_to_cpu(pixel[1]); - out_pixel->b = le16_to_cpu(pixel[0]); + return out_pixel; } -static void RGB565_to_argb_u16(const u8 *in_pixel, struct pixel_argb_u16 *out_pixel) +static struct pixel_argb_u16 argb_u16_from_RGB565(const u16 *pixel) { - u16 *pixel = (u16 *)in_pixel; + struct pixel_argb_u16 out_pixel; s64 fp_rb_ratio = drm_fixp_div(drm_int2fixp(65535), drm_int2fixp(31)); s64 fp_g_ratio = drm_fixp_div(drm_int2fixp(65535), drm_int2fixp(63)); @@ -167,12 +138,26 @@ static void RGB565_to_argb_u16(const u8 *in_pixel, struct pixel_argb_u16 *out_pi s64 fp_g = drm_int2fixp((rgb_565 >> 5) & 0x3f); s64 fp_b = drm_int2fixp(rgb_565 & 0x1f); - out_pixel->a = (u16)0xffff; - out_pixel->r = drm_fixp2int_round(drm_fixp_mul(fp_r, fp_rb_ratio)); - out_pixel->g = drm_fixp2int_round(drm_fixp_mul(fp_g, fp_g_ratio)); - out_pixel->b = drm_fixp2int_round(drm_fixp_mul(fp_b, fp_rb_ratio)); + out_pixel.a = (u16)0xffff; + out_pixel.r = drm_fixp2int_round(drm_fixp_mul(fp_r, fp_rb_ratio)); + out_pixel.g = drm_fixp2int_round(drm_fixp_mul(fp_g, fp_g_ratio)); + out_pixel.b = drm_fixp2int_round(drm_fixp_mul(fp_b, fp_rb_ratio)); + + return out_pixel; } +/* + * The following functions are read_line function for each pixel format supported by VKMS. + * + * They read a line starting at the point @x_start,@y_start following the @direction. The result + * is stored in @out_pixel and in the format ARGB16161616. + * + * Those function are very similar, but it is required for performance reason. In the past, some + * experiment were done, and with a generic loop the performance are very reduced [1]. + * + * [1]: https://lore.kernel.org/dri-devel/d258c8dc-78e9-4509-9037-a98f7f33b3a3@riseup.net/ + */ + /** * black_to_argb_u16() - pixel_read callback which always read black * @@ -180,42 +165,101 @@ static void RGB565_to_argb_u16(const u8 *in_pixel, struct pixel_argb_u16 *out_pi * It is used to avoid null pointer to be used as a function. In theory, this function should * never be called, except if you found a bug in the driver/DRM core. */ -static void black_to_argb_u16(const u8 *in_pixel, struct pixel_argb_u16 *out_pixel) +static void black_to_argb_u16(const struct vkms_plane_state *plane, int x_start, + int y_start, enum pixel_read_direction direction, int count, + struct pixel_argb_u16 out_pixel[]) { - out_pixel->a = (u16) 0xFFFF; - out_pixel->r = 0; - out_pixel->g = 0; - out_pixel->b = 0; + struct pixel_argb_u16 *end = out_pixel + count; + + while (out_pixel < end) { + *out_pixel = argb_u16_from_u8888(255, 0, 0, 0); + out_pixel += 1; + } } -/** - * vkms_compose_row - compose a single row of a plane - * @stage_buffer: output line with the composed pixels - * @plane: state of the plane that is being composed - * @y: y coordinate of the row - * - * This function composes a single row of a plane. It gets the source pixels - * through the y coordinate (see get_packed_src_addr()) and goes linearly - * through the source pixel, reading the pixels and converting it to - * ARGB16161616 (see the pixel_read() callback). For rotate-90 and rotate-270, - * the source pixels are not traversed linearly. The source pixels are queried - * on each iteration in order to traverse the pixels vertically. - */ -void vkms_compose_row(struct line_buffer *stage_buffer, struct vkms_plane_state *plane, int y) +static void ARGB8888_read_line(const struct vkms_plane_state *plane, int x_start, int y_start, + enum pixel_read_direction direction, int count, + struct pixel_argb_u16 out_pixel[]) +{ + struct pixel_argb_u16 *end = out_pixel + count; + u8 *src_pixels = packed_pixels_addr(plane->frame_info, x_start, y_start, 0); + + int step = get_step_1x1(plane->frame_info->fb, direction, 0); + + while (out_pixel < end) { + u8 *px = (u8 *)src_pixels; + *out_pixel = argb_u16_from_u8888(px[3], px[2], px[1], px[0]); + out_pixel += 1; + src_pixels += step; + } +} + +static void XRGB8888_read_line(const struct vkms_plane_state *plane, int x_start, int y_start, + enum pixel_read_direction direction, int count, + struct pixel_argb_u16 out_pixel[]) +{ + struct pixel_argb_u16 *end = out_pixel + count; + u8 *src_pixels = packed_pixels_addr(plane->frame_info, x_start, y_start, 0); + + int step = get_step_1x1(plane->frame_info->fb, direction, 0); + + while (out_pixel < end) { + u8 *px = (u8 *)src_pixels; + *out_pixel = argb_u16_from_u8888(255, px[2], px[1], px[0]); + out_pixel += 1; + src_pixels += step; + } +} + +static void ARGB16161616_read_line(const struct vkms_plane_state *plane, int x_start, + int y_start, enum pixel_read_direction direction, int count, + struct pixel_argb_u16 out_pixel[]) +{ + struct pixel_argb_u16 *end = out_pixel + count; + u8 *src_pixels = packed_pixels_addr(plane->frame_info, x_start, y_start, 0); + + int step = get_step_1x1(plane->frame_info->fb, direction, 0); + + while (out_pixel < end) { + u16 *px = (u16 *)src_pixels; + *out_pixel = argb_u16_from_u16161616(px[3], px[2], px[1], px[0]); + out_pixel += 1; + src_pixels += step; + } +} + +static void XRGB16161616_read_line(const struct vkms_plane_state *plane, int x_start, + int y_start, enum pixel_read_direction direction, int count, + struct pixel_argb_u16 out_pixel[]) +{ + struct pixel_argb_u16 *end = out_pixel + count; + u8 *src_pixels = packed_pixels_addr(plane->frame_info, x_start, y_start, 0); + + int step = get_step_1x1(plane->frame_info->fb, direction, 0); + + while (out_pixel < end) { + u16 *px = (u16 *)src_pixels; + *out_pixel = argb_u16_from_u16161616(0xFFFF, px[2], px[1], px[0]); + out_pixel += 1; + src_pixels += step; + } +} + +static void RGB565_read_line(const struct vkms_plane_state *plane, int x_start, + int y_start, enum pixel_read_direction direction, int count, + struct pixel_argb_u16 out_pixel[]) { - struct pixel_argb_u16 *out_pixels = stage_buffer->pixels; - struct vkms_frame_info *frame_info = plane->frame_info; - u8 *src_pixels = get_packed_src_addr(frame_info, y, 0); - int limit = min_t(size_t, drm_rect_width(&frame_info->dst), stage_buffer->n_pixels); + struct pixel_argb_u16 *end = out_pixel + count; + u8 *src_pixels = packed_pixels_addr(plane->frame_info, x_start, y_start, 0); - for (size_t x = 0; x < limit; x++, src_pixels += frame_info->fb->format->cpp[0]) { - int x_pos = get_x_position(frame_info, limit, x); + int step = get_step_1x1(plane->frame_info->fb, direction, 0); - if (drm_rotation_90_or_270(frame_info->rotation)) - src_pixels = get_packed_src_addr(frame_info, x + frame_info->rotated.y1, 0) - + frame_info->fb->format->cpp[0] * y; + while (out_pixel < end) { + u16 *px = (u16 *)src_pixels; - plane->pixel_read(src_pixels, &out_pixels[x_pos]); + *out_pixel = argb_u16_from_RGB565(px); + out_pixel += 1; + src_pixels += step; } } @@ -321,25 +365,25 @@ void vkms_writeback_row(struct vkms_writeback_job *wb, } /** - * Retrieve the correct read_pixel function for a specific format. + * Retrieve the correct read_line function for a specific format. * If the format is not supported by VKMS a warn is emitted and a dummy "always read black" * function is returned. * * @format: DRM_FORMAT_* value for which to obtain a conversion function (see [drm_fourcc.h]) */ -pixel_read_t get_pixel_read_function(u32 format) +pixel_read_line_t get_pixel_read_line_function(u32 format) { switch (format) { case DRM_FORMAT_ARGB8888: - return &ARGB8888_to_argb_u16; + return &ARGB8888_read_line; case DRM_FORMAT_XRGB8888: - return &XRGB8888_to_argb_u16; + return &XRGB8888_read_line; case DRM_FORMAT_ARGB16161616: - return &ARGB16161616_to_argb_u16; + return &ARGB16161616_read_line; case DRM_FORMAT_XRGB16161616: - return &XRGB16161616_to_argb_u16; + return &XRGB16161616_read_line; case DRM_FORMAT_RGB565: - return &RGB565_to_argb_u16; + return &RGB565_read_line; default: /* * This is a bug in vkms_plane_atomic_check. All the supported diff --git a/drivers/gpu/drm/vkms/vkms_formats.h b/drivers/gpu/drm/vkms/vkms_formats.h index 3ecea4563254..8d2bef95ff79 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.h +++ b/drivers/gpu/drm/vkms/vkms_formats.h @@ -5,7 +5,7 @@ #include "vkms_drv.h" -pixel_read_t get_pixel_read_function(u32 format); +pixel_read_line_t get_pixel_read_line_function(u32 format); pixel_write_t get_pixel_write_function(u32 format); diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index 10e9b23dab28..8875bed76410 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -112,7 +112,6 @@ static void vkms_plane_atomic_update(struct drm_plane *plane, frame_info = vkms_plane_state->frame_info; memcpy(&frame_info->src, &new_state->src, sizeof(struct drm_rect)); memcpy(&frame_info->dst, &new_state->dst, sizeof(struct drm_rect)); - memcpy(&frame_info->rotated, &new_state->dst, sizeof(struct drm_rect)); frame_info->fb = fb; memcpy(&frame_info->map, &shadow_plane_state->data, sizeof(frame_info->map)); drm_framebuffer_get(frame_info->fb); @@ -122,10 +121,8 @@ static void vkms_plane_atomic_update(struct drm_plane *plane, DRM_MODE_REFLECT_X | DRM_MODE_REFLECT_Y); - drm_rect_rotate(&frame_info->rotated, drm_rect_width(&frame_info->rotated), - drm_rect_height(&frame_info->rotated), frame_info->rotation); - vkms_plane_state->pixel_read = get_pixel_read_function(fmt); + vkms_plane_state->pixel_read_line = get_pixel_read_line_function(fmt); } static int vkms_plane_atomic_check(struct drm_plane *plane, From patchwork Mon Mar 4 15:28:16 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Louis Chauvet X-Patchwork-Id: 13580742 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6DF4BC5478C for ; Mon, 4 Mar 2024 15:29:36 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id DC7AD1122A8; Mon, 4 Mar 2024 15:29:34 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=bootlin.com header.i=@bootlin.com header.b="WmebUhcJ"; dkim-atps=neutral Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) by gabe.freedesktop.org (Postfix) with ESMTPS id 7979A11205E for ; Mon, 4 Mar 2024 15:29:32 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id 2AD051C000D; Mon, 4 Mar 2024 15:29:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1709566171; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=dnaSpd8gQBPW2mCDvj7nDjUQi8Lv+iKD5qb1DicVeGs=; b=WmebUhcJmHP1xljSCOiAXdEh+LBTtatFvR/AnPra7Ek/CegVYRyG3N/TlpXUAVNsPLkERG ahX8D3bAYJrrcvdwvQxlDugNTyiF6dMacUtlWGpqkvDXNfoRL48tbqLCJZ5sRECy7F5wry +8Gs3BqlkWltCMFAiENRGpUOI4/7z3YbEgKI+iFr9PjFDxvhltWY6d+XOmfu/L38JUabSU /vQT/nFeYKFNOGSUNC3/nguL0rNW4cGWvR255y4VZqlWc6Fbsu+sFQlKJAlCTgDjUBuVn1 Hmtr7G+GYl1xhUqB/CX3AxxA88uLKzPjbaPF6r3tJmjiZ1OUUZxqLu/NsGYrHA== From: Louis Chauvet Date: Mon, 04 Mar 2024 16:28:16 +0100 Subject: [PATCH v4 11/14] drm/vkms: Add YUV support MIME-Version: 1.0 Message-Id: <20240304-yuv-v4-11-76beac8e9793@bootlin.com> References: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> In-Reply-To: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> To: Rodrigo Siqueira , Melissa Wen , =?utf-8?q?Ma=C3=ADra_Canal?= , Haneen Mohammed , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , arthurgrillo@riseup.net, Jonathan Corbet , pekka.paalanen@haloniitty.fi Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, jeremie.dautheribes@bootlin.com, miquel.raynal@bootlin.com, thomas.petazzoni@bootlin.com, seanpaul@google.com, marcheu@google.com, nicolejadeyee@google.com, Louis Chauvet X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=17940; i=louis.chauvet@bootlin.com; h=from:subject:message-id; bh=ENcAK3ynLvDm24VjMw7uHS+29wtrHy71ENTfOEy1bHs=; b=owEBbQKS/ZANAwAIASCtLsZbECziAcsmYgBl5ejM/XIO+t56GWpsyH+wQU/veQdqyHaEvnFFB8dF +wp2vbeJAjMEAAEIAB0WIQRPj7g/vng8MQxQWQQgrS7GWxAs4gUCZeXozAAKCRAgrS7GWxAs4rf2D/ 4wGOkjYVqrBsuXnPd1V3z2ChA5Pf5+khCvocrJfRTrP7yHrLeVB34dN4i8UJEneSSHiTHOgNvQ4CMB yKa+tIxPakpzmm+4Lz8NR1S6rzPtPEddss5Qq0c2aKuDnlp19jWfMX7R/6IyCSWE4r0POyI7LOzFJo 0B1PmSq+KDOa+52tWWM71CUA71hupjB1VMum5INMnuNp0+4ZcggjAGqkGfwTFmjdLDNe26F4k3uOti k/X02+0SCh9C7C+XDPYg1YG+M69j0mAIAYaMYAg6OhOxaSKvlJsZh03oEFWYpWTj+T9gKFCbsrCKs6 ry2UcbGSurUPnxxkQ22w88+80bqKbLwwa6PuI4nxyuQQfB9jSJtVCxCd/ZKrPgbqtsr9gsweYOlS/t IW2YkkN34v9v0GPuPbh0dsOttbLZHRd+xbwYZC6kwHugalh7yHb4arzexPH50H+utujlozzN4jVwTT u0ZoHcJ7yhMePtu2dLAC2U0SgLGDyGxs2O8Fv0nYvgsPU6QAgGBbYdYOfH5J+MoOZkrGTVnQ7v6I0+ bwmAz2vV7/STj8U/DzLi0Jx+aPufSlEa4bxwG8SGxZRJF2ZGTFpz1SbgAQKZOb1fsml24Pgtv50Xp5 HnGQFbkkpUK+EfKdRKsyPVAx2slvX9HARDcPgniDMueq0z2sjKeLhg9Kc0+A== X-Developer-Key: i=louis.chauvet@bootlin.com; a=openpgp; fpr=8B7104AE9A272D6693F527F2EC1883F55E0B40A5 X-GND-Sasl: louis.chauvet@bootlin.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Arthur Grillo Add support to the YUV formats bellow: - NV12/NV16/NV24 - NV21/NV61/NV42 - YUV420/YUV422/YUV444 - YVU420/YVU422/YVU444 The conversion from yuv to rgb is done with fixed-point arithmetic, using 32.32 floats. To do the conversion, a specific matrix must be used for each color range (DRM_COLOR_*_RANGE) and encoding (DRM_COLOR_*). This matrix is stored in the `conversion_matrix` struct, along with the specific y_offset needed. This matrix is queried only once, in `vkms_plane_atomic_update` and stored in a `vkms_plane_state`. Those conversion matrices of each encoding and range were obtained by rounding the values of the original conversion matrices multiplied by 2^32. This is done to avoid the use of fixed point operations. The same reading function is used for YUV and YVU formats. As the only difference between those two category of formats is the order of field, a simple swap in conversion matrix columns allows using the same function. Signed-off-by: Arthur Grillo [Louis Chauvet: - Adapted Arthur's work - Implemented the read_line_t callbacks for yuv - add struct conversion_matrix - remove struct pixel_yuv_u8 - update the commit message] Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_drv.h | 23 +++ drivers/gpu/drm/vkms/vkms_formats.c | 374 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/vkms/vkms_formats.h | 4 + drivers/gpu/drm/vkms/vkms_plane.c | 16 +- 4 files changed, 416 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vkms/vkms_drv.h b/drivers/gpu/drm/vkms/vkms_drv.h index 23e1d247468d..393b76e7c694 100644 --- a/drivers/gpu/drm/vkms/vkms_drv.h +++ b/drivers/gpu/drm/vkms/vkms_drv.h @@ -99,6 +99,28 @@ typedef void (*pixel_read_line_t)(const struct vkms_plane_state *plane, int x_st int y_start, enum pixel_read_direction direction, int count, struct pixel_argb_u16 out_pixel[]); + +/** + * CONVERSION_MATRIX_FLOAT_DEPTH - Number of digits after the point for conversion matrix values + */ +#define CONVERSION_MATRIX_FLOAT_DEPTH 32 + +/** + * struct conversion_matrix - Matrix to use for a specific encoding and range + * + * @matrix: Conversion matrix from yuv to rgb. The matrix is stored in a row-major manner and is + * used to compute rgb values from yuv values: + * [[r],[g],[b]] = @matrix * [[y],[u],[v]] + * OR for yvu formats: + * [[r],[g],[b]] = @matrix * [[y],[v],[u]] + * The values of the matrix are fixed floats, 32.CONVERSION_MATRIX_FLOAT_DEPTH + * @y_offest: Offset to apply on the y value. + */ +struct conversion_matrix { + s64 matrix[3][3]; + s64 y_offset; +}; + /** * vkms_plane_state - Driver specific plane state * @base: base plane state @@ -110,6 +132,7 @@ struct vkms_plane_state { struct drm_shadow_plane_state base; struct vkms_frame_info *frame_info; pixel_read_line_t pixel_read_line; + struct conversion_matrix *conversion_matrix; }; struct vkms_plane { diff --git a/drivers/gpu/drm/vkms/vkms_formats.c b/drivers/gpu/drm/vkms/vkms_formats.c index 87af3962ee12..d9b70d9b99ef 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.c +++ b/drivers/gpu/drm/vkms/vkms_formats.c @@ -90,6 +90,45 @@ static int get_step_1x1(struct drm_framebuffer *fb, enum pixel_read_direction di return 0; } +/** + * get_subsampling() - Get the subsampling divisor value on a specific direction + */ +static int get_subsampling(const struct drm_format_info *format, + enum pixel_read_direction direction) +{ + switch (direction) { + case READ_BOTTOM_TO_TOP: + case READ_TOP_TO_BOTTOM: + return format->vsub; + case READ_RIGHT_TO_LEFT: + case READ_LEFT_TO_RIGHT: + return format->hsub; + } + WARN_ONCE(true, "Invalid direction for pixel reading: %d\n", direction); + return 1; +} + +/** + * get_subsampling_offset() - An offset for keeping the chroma siting consistent regardless of + * x_start and y_start values + */ +static int get_subsampling_offset(enum pixel_read_direction direction, int x_start, int y_start) +{ + switch (direction) { + case READ_BOTTOM_TO_TOP: + return -y_start; + case READ_TOP_TO_BOTTOM: + return y_start; + case READ_RIGHT_TO_LEFT: + return -x_start; + case READ_LEFT_TO_RIGHT: + return x_start; + } + WARN_ONCE(true, "Invalid direction for pixel reading: %d\n", direction); + return 0; +} + + /* * The following functions take pixel data (a, r, g, b, pixel, ...), convert them to the format * ARGB16161616 in out_pixel. @@ -146,6 +185,40 @@ static struct pixel_argb_u16 argb_u16_from_RGB565(const u16 *pixel) return out_pixel; } +static struct pixel_argb_u16 argb_u16_from_yuv888(u8 y, u8 cb, u8 cr, + struct conversion_matrix *matrix) +{ + u8 r, g, b; + s64 y_16, cb_16, cr_16; + s64 r_16, g_16, b_16; + + y_16 = y - matrix->y_offset; + cb_16 = cb - 128; + cr_16 = cr - 128; + + r_16 = matrix->matrix[0][0] * y_16 + matrix->matrix[0][1] * cb_16 + + matrix->matrix[0][2] * cr_16; + g_16 = matrix->matrix[1][0] * y_16 + matrix->matrix[1][1] * cb_16 + + matrix->matrix[1][2] * cr_16; + b_16 = matrix->matrix[2][0] * y_16 + matrix->matrix[2][1] * cb_16 + + matrix->matrix[2][2] * cr_16; + + // rounding the values + r_16 = r_16 + (1LL << (CONVERSION_MATRIX_FLOAT_DEPTH - 4)); + g_16 = g_16 + (1LL << (CONVERSION_MATRIX_FLOAT_DEPTH - 4)); + b_16 = b_16 + (1LL << (CONVERSION_MATRIX_FLOAT_DEPTH - 4)); + + r_16 = clamp(r_16, 0, (1LL << (CONVERSION_MATRIX_FLOAT_DEPTH + 8)) - 1); + g_16 = clamp(g_16, 0, (1LL << (CONVERSION_MATRIX_FLOAT_DEPTH + 8)) - 1); + b_16 = clamp(b_16, 0, (1LL << (CONVERSION_MATRIX_FLOAT_DEPTH + 8)) - 1); + + r = r_16 >> CONVERSION_MATRIX_FLOAT_DEPTH; + g = g_16 >> CONVERSION_MATRIX_FLOAT_DEPTH; + b = b_16 >> CONVERSION_MATRIX_FLOAT_DEPTH; + + return argb_u16_from_u8888(255, r, g, b); +} + /* * The following functions are read_line function for each pixel format supported by VKMS. * @@ -263,6 +336,70 @@ static void RGB565_read_line(const struct vkms_plane_state *plane, int x_start, } } +/* + * This callback can be used for yuv and yvu formats, given a properly modified conversion matrix + * (column inversion) + */ +static void semi_planar_yuv_read_line(const struct vkms_plane_state *plane, int x_start, + int y_start, enum pixel_read_direction direction, int count, + struct pixel_argb_u16 out_pixel[]) +{ + u8 *y_plane = packed_pixels_addr(plane->frame_info, x_start, y_start, 0); + u8 *uv_plane = packed_pixels_addr(plane->frame_info, + x_start / plane->frame_info->fb->format->hsub, + y_start / plane->frame_info->fb->format->vsub, + 1); + int step_y = get_step_1x1(plane->frame_info->fb, direction, 0); + int step_uv = get_step_1x1(plane->frame_info->fb, direction, 1); + int subsampling = get_subsampling(plane->frame_info->fb->format, direction); + int subsampling_offset = get_subsampling_offset(direction, x_start, y_start); + struct conversion_matrix *conversion_matrix = plane->conversion_matrix; + + for (int i = 0; i < count; i++) { + *out_pixel = argb_u16_from_yuv888(y_plane[0], uv_plane[0], uv_plane[1], + conversion_matrix); + out_pixel += 1; + y_plane += step_y; + if ((i + subsampling_offset + 1) % subsampling == 0) + uv_plane += step_uv; + } +} + +/* + * This callback can be used for yuv and yvu formats, given a properly modified conversion matrix + * (column inversion) + */ +static void planar_yuv_read_line(const struct vkms_plane_state *plane, int x_start, + int y_start, enum pixel_read_direction direction, int count, + struct pixel_argb_u16 out_pixel[]) +{ + u8 *y_plane = packed_pixels_addr(plane->frame_info, x_start, y_start, 0); + u8 *u_plane = packed_pixels_addr(plane->frame_info, + x_start / plane->frame_info->fb->format->hsub, + y_start / plane->frame_info->fb->format->vsub, + 1); + u8 *v_plane = packed_pixels_addr(plane->frame_info, + x_start / plane->frame_info->fb->format->hsub, + y_start / plane->frame_info->fb->format->vsub, + 2); + int step_y = get_step_1x1(plane->frame_info->fb, direction, 0); + int step_u = get_step_1x1(plane->frame_info->fb, direction, 1); + int step_v = get_step_1x1(plane->frame_info->fb, direction, 2); + int subsampling = get_subsampling(plane->frame_info->fb->format, direction); + int subsampling_offset = get_subsampling_offset(direction, x_start, y_start); + struct conversion_matrix *conversion_matrix = plane->conversion_matrix; + + for (int i = 0; i < count; i++) { + *out_pixel = argb_u16_from_yuv888(*y_plane, *u_plane, *v_plane, conversion_matrix); + out_pixel += 1; + y_plane += step_y; + if ((i + subsampling_offset + 1) % subsampling == 0) { + u_plane += step_u; + v_plane += step_v; + } + } +} + /* * The following functions take one argb_u16 pixel and convert it to a specific format. The * result is stored in @out_pixel. @@ -384,6 +521,20 @@ pixel_read_line_t get_pixel_read_line_function(u32 format) return &XRGB16161616_read_line; case DRM_FORMAT_RGB565: return &RGB565_read_line; + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV16: + case DRM_FORMAT_NV24: + case DRM_FORMAT_NV21: + case DRM_FORMAT_NV61: + case DRM_FORMAT_NV42: + return &semi_planar_yuv_read_line; + case DRM_FORMAT_YUV420: + case DRM_FORMAT_YUV422: + case DRM_FORMAT_YUV444: + case DRM_FORMAT_YVU420: + case DRM_FORMAT_YVU422: + case DRM_FORMAT_YVU444: + return &planar_yuv_read_line; default: /* * This is a bug in vkms_plane_atomic_check. All the supported @@ -400,6 +551,229 @@ pixel_read_line_t get_pixel_read_line_function(u32 format) } } +/** + * get_conversion_matrix_to_argb_u16() - Retrieve the correct yuv to rgb conversion matrix for a + * given encoding and range. + * + * If the matrix is not found, return a null pointer. In all other cases, it return a simple + * diagonal matrix, which act as a "no-op". + * + * @format: DRM_FORMAT_* value for which to obtain a conversion function (see [drm_fourcc.h]) + * @encoding: DRM_COLOR_* value for which to obtain a conversion matrix + * @range: DRM_COLOR_*_RANGE value for which to obtain a conversion matrix + */ +struct conversion_matrix * +get_conversion_matrix_to_argb_u16(u32 format, enum drm_color_encoding encoding, + enum drm_color_range range) +{ + static struct conversion_matrix no_operation = { + .matrix = { + { 4294967296, 0, 0, }, + { 0, 4294967296, 0, }, + { 0, 0, 4294967296, }, + }, + .y_offset = 0, + }; + static struct conversion_matrix yuv_bt601_full = { + .matrix = { + { 4294967296, 0, 6021544149 }, + { 4294967296, -1478054095, -3067191994 }, + { 4294967296, 7610682049, 0 }, + }, + .y_offset = 0, + }; + static struct conversion_matrix yuv_bt601_limited = { + .matrix = { + { 5020601039, 0, 6881764740 }, + { 5020601039, -1689204679, -3505362278 }, + { 5020601039, 8697922339, 0 }, + }, + .y_offset = 16, + }; + static struct conversion_matrix yuv_bt709_full = { + .matrix = { + { 4294967296, 0, 6763714498 }, + { 4294967296, -804551626, -2010578443 }, + { 4294967296, 7969741314, 0 }, + }, + .y_offset = 0, + }; + static struct conversion_matrix yuv_bt709_limited = { + .matrix = { + { 5020601039, 0, 7729959424 }, + { 5020601039, -919487572, -2297803934 }, + { 5020601039, 9108275786, 0 }, + }, + .y_offset = 16, + }; + static struct conversion_matrix yuv_bt2020_full = { + .matrix = { + { 4294967296, 0, 6333358775 }, + { 4294967296, -706750298, -2453942994 }, + { 4294967296, 8080551471, 0 }, + }, + .y_offset = 0, + }; + static struct conversion_matrix yuv_bt2020_limited = { + .matrix = { + { 5020601039, 0, 7238124312 }, + { 5020601039, -807714626, -2804506279 }, + { 5020601039, 9234915964, 0 }, + }, + .y_offset = 16, + }; + static struct conversion_matrix yvu_bt601_full = { + .matrix = { + { 4294967296, 6021544149, 0 }, + { 4294967296, -3067191994, -1478054095 }, + { 4294967296, 0, 7610682049 }, + }, + .y_offset = 0, + }; + static struct conversion_matrix yvu_bt601_limited = { + .matrix = { + { 5020601039, 6881764740, 0 }, + { 5020601039, -3505362278, -1689204679 }, + { 5020601039, 0, 8697922339 }, + }, + .y_offset = 16, + }; + static struct conversion_matrix yvu_bt709_full = { + .matrix = { + { 4294967296, 6763714498, 0 }, + { 4294967296, -2010578443, -804551626 }, + { 4294967296, 0, 7969741314 }, + }, + .y_offset = 0, + }; + static struct conversion_matrix yvu_bt709_limited = { + .matrix = { + { 5020601039, 7729959424, 0 }, + { 5020601039, -2297803934, -919487572 }, + { 5020601039, 0, 9108275786 }, + }, + .y_offset = 16, + }; + static struct conversion_matrix yvu_bt2020_full = { + .matrix = { + { 4294967296, 6333358775, 0 }, + { 4294967296, -2453942994, -706750298 }, + { 4294967296, 0, 8080551471 }, + }, + .y_offset = 0, + }; + static struct conversion_matrix yvu_bt2020_limited = { + .matrix = { + { 5020601039, 7238124312, 0 }, + { 5020601039, -2804506279, -807714626 }, + { 5020601039, 0, 9234915964 }, + }, + .y_offset = 16, + }; + + /* Breaking in this switch means that the color format+encoding+range is not supported */ + switch (format) { + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV16: + case DRM_FORMAT_NV24: + case DRM_FORMAT_YUV420: + case DRM_FORMAT_YUV422: + case DRM_FORMAT_YUV444: + switch (encoding) { + case DRM_COLOR_YCBCR_BT601: + switch (range) { + case DRM_COLOR_YCBCR_LIMITED_RANGE: + return &yuv_bt601_limited; + case DRM_COLOR_YCBCR_FULL_RANGE: + return &yuv_bt601_full; + case DRM_COLOR_RANGE_MAX: + break; + } + break; + case DRM_COLOR_YCBCR_BT709: + switch (range) { + case DRM_COLOR_YCBCR_LIMITED_RANGE: + return &yuv_bt709_limited; + case DRM_COLOR_YCBCR_FULL_RANGE: + return &yuv_bt709_full; + case DRM_COLOR_RANGE_MAX: + break; + } + break; + case DRM_COLOR_YCBCR_BT2020: + switch (range) { + case DRM_COLOR_YCBCR_LIMITED_RANGE: + return &yuv_bt2020_limited; + case DRM_COLOR_YCBCR_FULL_RANGE: + return &yuv_bt2020_full; + case DRM_COLOR_RANGE_MAX: + break; + } + break; + case DRM_COLOR_ENCODING_MAX: + break; + } + break; + case DRM_FORMAT_YVU420: + case DRM_FORMAT_YVU422: + case DRM_FORMAT_YVU444: + case DRM_FORMAT_NV21: + case DRM_FORMAT_NV61: + case DRM_FORMAT_NV42: + switch (encoding) { + case DRM_COLOR_YCBCR_BT601: + switch (range) { + case DRM_COLOR_YCBCR_LIMITED_RANGE: + return &yvu_bt601_limited; + case DRM_COLOR_YCBCR_FULL_RANGE: + return &yvu_bt601_full; + case DRM_COLOR_RANGE_MAX: + break; + } + break; + case DRM_COLOR_YCBCR_BT709: + switch (range) { + case DRM_COLOR_YCBCR_LIMITED_RANGE: + return &yvu_bt709_limited; + case DRM_COLOR_YCBCR_FULL_RANGE: + return &yvu_bt709_full; + case DRM_COLOR_RANGE_MAX: + break; + } + break; + case DRM_COLOR_YCBCR_BT2020: + switch (range) { + case DRM_COLOR_YCBCR_LIMITED_RANGE: + return &yvu_bt2020_limited; + case DRM_COLOR_YCBCR_FULL_RANGE: + return &yvu_bt2020_full; + case DRM_COLOR_RANGE_MAX: + break; + } + break; + case DRM_COLOR_ENCODING_MAX: + break; + } + break; + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_XRGB8888: + case DRM_FORMAT_ARGB16161616: + case DRM_FORMAT_XRGB16161616: + case DRM_FORMAT_RGB565: + /* + * Those formats are supported, but they don't need a conversion matrix. Return + * a valid pointer to avoid kernel panic in case this matrix is used/checked + * somewhere. + */ + return &no_operation; + default: + break; + } + WARN(true, "Unsupported encoding (%d), range (%d) and format (%4cc) combination\n", + encoding, range, format); + return &no_operation; +} + /** * Retrieve the correct write_pixel function for a specific format. * If the format is not supported by VKMS a warn is emitted and a dummy "don't do anything" diff --git a/drivers/gpu/drm/vkms/vkms_formats.h b/drivers/gpu/drm/vkms/vkms_formats.h index 8d2bef95ff79..e1d324764b17 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.h +++ b/drivers/gpu/drm/vkms/vkms_formats.h @@ -9,4 +9,8 @@ pixel_read_line_t get_pixel_read_line_function(u32 format); pixel_write_t get_pixel_write_function(u32 format); +struct conversion_matrix * +get_conversion_matrix_to_argb_u16(u32 format, enum drm_color_encoding encoding, + enum drm_color_range range); + #endif /* _VKMS_FORMATS_H_ */ diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index 8875bed76410..93d0a39fa8c5 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -17,7 +17,19 @@ static const u32 vkms_formats[] = { DRM_FORMAT_XRGB8888, DRM_FORMAT_XRGB16161616, DRM_FORMAT_ARGB16161616, - DRM_FORMAT_RGB565 + DRM_FORMAT_RGB565, + DRM_FORMAT_NV12, + DRM_FORMAT_NV16, + DRM_FORMAT_NV24, + DRM_FORMAT_NV21, + DRM_FORMAT_NV61, + DRM_FORMAT_NV42, + DRM_FORMAT_YUV420, + DRM_FORMAT_YUV422, + DRM_FORMAT_YUV444, + DRM_FORMAT_YVU420, + DRM_FORMAT_YVU422, + DRM_FORMAT_YVU444 }; static struct drm_plane_state * @@ -123,6 +135,8 @@ static void vkms_plane_atomic_update(struct drm_plane *plane, vkms_plane_state->pixel_read_line = get_pixel_read_line_function(fmt); + vkms_plane_state->conversion_matrix = get_conversion_matrix_to_argb_u16 + (fmt, new_state->color_encoding, new_state->color_range); } static int vkms_plane_atomic_check(struct drm_plane *plane, From patchwork Mon Mar 4 15:28:17 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Louis Chauvet X-Patchwork-Id: 13580743 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4BFBDC54E4A for ; Mon, 4 Mar 2024 15:29:37 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 075A31122AC; Mon, 4 Mar 2024 15:29:35 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=bootlin.com header.i=@bootlin.com header.b="TlcsieNk"; dkim-atps=neutral Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) by gabe.freedesktop.org (Postfix) with ESMTPS id 721DB11205E for ; Mon, 4 Mar 2024 15:29:33 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id 3540A1C0010; Mon, 4 Mar 2024 15:29:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1709566172; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=26jfrCIS+JUx4NErVJifAR1jnrL2bLpCNnl9zevyG7E=; b=TlcsieNkAKVFD19DF8gNUqZZYrv3I8hzwSXVbo+CbM9BHBMeA2/5wD8YnKfhWvXv597Nro RY3VzSwNJBS8UMkoBi8JGoJvu4iENP7udsOZywqu82ZFa7LBwBLE0QGP+CwPgrZJtHXqxp BNx+5NDKtsxunj1GfINU+O71d+yiR263jiN1MNd1qfLrAZTsToi93UHpQl3JIoeGchKbhg bf21qE3YtoZkAI+oBkPIDqDlcbncLw4jDBiqUTN1AOcBd74r7uaScTpU0E97gHLpFnaNip E1n00vZQrZZzO+PbO3e6qM4ZYnerw0cHj9iClY6WY8pYgUm8lBtj7ld6G87nNA== From: Louis Chauvet Date: Mon, 04 Mar 2024 16:28:17 +0100 Subject: [PATCH v4 12/14] drm/vkms: Add range and encoding properties to the plane MIME-Version: 1.0 Message-Id: <20240304-yuv-v4-12-76beac8e9793@bootlin.com> References: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> In-Reply-To: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> To: Rodrigo Siqueira , Melissa Wen , =?utf-8?q?Ma=C3=ADra_Canal?= , Haneen Mohammed , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , arthurgrillo@riseup.net, Jonathan Corbet , pekka.paalanen@haloniitty.fi Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, jeremie.dautheribes@bootlin.com, miquel.raynal@bootlin.com, thomas.petazzoni@bootlin.com, seanpaul@google.com, marcheu@google.com, nicolejadeyee@google.com, Louis Chauvet X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=1196; i=louis.chauvet@bootlin.com; h=from:subject:message-id; bh=Cnbjjk3lDbLwEuT/PRDsmPkqIyFjzRh3yTX0NhmzJqo=; b=owEBbQKS/ZANAwAIASCtLsZbECziAcsmYgBl5ejMXZrje6UM/C+p7h5+cW+P2NbkwUYAEBIyxQsi FyLQEMGJAjMEAAEIAB0WIQRPj7g/vng8MQxQWQQgrS7GWxAs4gUCZeXozAAKCRAgrS7GWxAs4iCTD/ 9TRgvNYIht1ieF035Yxk5hgxRJjWNAtpZojSWqH1NfhyABwXVy3Pu6aEAy+voqlrx46umtKIwjbqGe WAp4YdgEEoc3y4HBvkk8/AxwbIHCKPKUn/cBuLh+Oerkk8Wo+oh+V741ie7YlOJt7WG12QTeJlBJRU Ff+J2Y2v+Mf7QWh+xIHqlb/VmyYxnWSwNVqAJdtc/lvzPBTi+VzEqWAE4GJ/7zKgwLPw5aZlQ7ZAfW uLcSOjHGZBF9PDPyC3myovy/BDKpf+gQd7IJSteRNsJJSX0Kgd5qyCIdOxq95nF+R43Dx6q+tS2jRN 9XRXGLzdgyVv+TGQfhYBL7umwwmuaJMCgNeOVrvUxe4UP+C0IGrnRpY0yjxhFAQ5Gq1VGwDxKoHBcN uzYNo6DBAYkqoO7xCPcwh5W9w6fE+l1yAgu/uQm800FvOEP1XBdhBvYenWA0lutozTlZPkpxvdwXik Gw8kEFWbBKdkNvMr+yACQIKBqwgtfa+pGZeRz++klBSSU8mm19xdklVXvavmEwVRuOKDJHpv6uHvv2 ErsWkFUAY3sBVKxpbWPtRddvU+ha1bKEP0xRUUzx0bWSl+jJ36O/kVyCmiWo/2/k5+qqhlXEy1+8Sv QmbNLXEPSC+xdVVSDaRYImqZYb6PR96+uRf2kafsW1HJYL1IaGmyrMjG1FJw== X-Developer-Key: i=louis.chauvet@bootlin.com; a=openpgp; fpr=8B7104AE9A272D6693F527F2EC1883F55E0B40A5 X-GND-Sasl: louis.chauvet@bootlin.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Arthur Grillo Now that the driver internally handles these quantization ranges and YUV encoding matrices, expose the UAPI for setting them. Signed-off-by: Arthur Grillo [Louis Chauvet: retained only relevant parts, updated the commit message] Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/vkms_plane.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index 93d0a39fa8c5..4bda9ab6e2a4 100644 --- a/drivers/gpu/drm/vkms/vkms_plane.c +++ b/drivers/gpu/drm/vkms/vkms_plane.c @@ -223,5 +223,14 @@ struct vkms_plane *vkms_plane_init(struct vkms_device *vkmsdev, drm_plane_create_rotation_property(&plane->base, DRM_MODE_ROTATE_0, DRM_MODE_ROTATE_MASK | DRM_MODE_REFLECT_MASK); + drm_plane_create_color_properties(&plane->base, + BIT(DRM_COLOR_YCBCR_BT601) | + BIT(DRM_COLOR_YCBCR_BT709) | + BIT(DRM_COLOR_YCBCR_BT2020), + BIT(DRM_COLOR_YCBCR_LIMITED_RANGE) | + BIT(DRM_COLOR_YCBCR_FULL_RANGE), + DRM_COLOR_YCBCR_BT601, + DRM_COLOR_YCBCR_FULL_RANGE); + return plane; } From patchwork Mon Mar 4 15:28:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Louis Chauvet X-Patchwork-Id: 13580744 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 67F39C54E4A for ; Mon, 4 Mar 2024 15:29:39 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 265601122AF; Mon, 4 Mar 2024 15:29:38 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=bootlin.com header.i=@bootlin.com header.b="Xk4J9VU+"; dkim-atps=neutral Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) by gabe.freedesktop.org (Postfix) with ESMTPS id C2B241122A7 for ; Mon, 4 Mar 2024 15:29:34 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id 551711C0004; Mon, 4 Mar 2024 15:29:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1709566173; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=1mJQirOrh5uVlCQFN4AJsimww+6ayqe/xDiVoFk4V7I=; b=Xk4J9VU+pc7nMsKkFc0PCYSd0Uqy9K3tIKHRaV9ewrg7Rd/qEqHMCcMAqJwVa0TJrQBvHv O5qS1eBGut0j3WSf/UTmr2wj14SPT7Jk1i9VTvjeXtBhWTFwMtBJUUui+IO5qK8pka6HtC 6GDy5CUmLD38yQeF0vBcmShM00uM7kyvIs+wOg3HcntYmxLo/PhTQzpIF0AWBtJF7vRJ54 uwnFE6i2rnLbj7o18pUl2Aue6N9hK5xhibJygd1Mbvyr14QIvUaWl5w1pD+V1zARik6sjZ JhvS3EZZfOmfZJVWdYs0+sN2wwV+ngs7RvKww2OeuXT5NoHCETjIlsXcQWS7VA== From: Louis Chauvet Date: Mon, 04 Mar 2024 16:28:18 +0100 Subject: [PATCH v4 13/14] drm/vkms: Drop YUV formats TODO MIME-Version: 1.0 Message-Id: <20240304-yuv-v4-13-76beac8e9793@bootlin.com> References: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> In-Reply-To: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> To: Rodrigo Siqueira , Melissa Wen , =?utf-8?q?Ma=C3=ADra_Canal?= , Haneen Mohammed , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , arthurgrillo@riseup.net, Jonathan Corbet , pekka.paalanen@haloniitty.fi Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, jeremie.dautheribes@bootlin.com, miquel.raynal@bootlin.com, thomas.petazzoni@bootlin.com, seanpaul@google.com, marcheu@google.com, nicolejadeyee@google.com, Louis Chauvet X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=881; i=louis.chauvet@bootlin.com; h=from:subject:message-id; bh=cRkkP1b8eceTuEm0QTSGTTTnDinaYzDjRJLok06bIiI=; b=owEBbQKS/ZANAwAIASCtLsZbECziAcsmYgBl5ejN9NMOsH5mc7MJuPKBhjpy8/A2Pbt9HDaq6Wzi tKnejwmJAjMEAAEIAB0WIQRPj7g/vng8MQxQWQQgrS7GWxAs4gUCZeXozQAKCRAgrS7GWxAs4pO2D/ 96UYBmCNnqyEt/7G+7haOSQC/qglT/fzK77FF2xMd0MYFlrW8XGXuE9aq1Rj2QiCC4jTgVb597PaUU lkvUu4GKnfyBePKMCOEngZOWsW9duc0+Cqm6G/b9AoRAbQZQEU9t0Eb2XGk4LbcLfeadUdTAIan36B gKqFdJOFuNpJJog6MKfDjQxe0JzdVyiABSvwxCq6AfYO2HILZS2yqKcIA6ZdtgIYdm7mDvWhihtdyI gn3YmeNO1qTV9YKKI8b9BodFr3oe7KBAR1cwWNJD1E/8hQRzZWqmImfPWHyxBSHqt3tYgqasjMs+4X 6sGev7z6CmlaP2gVNcPvMPHj7ksawgVJ1dpwTakCGwDH32ayeoMC4wHlSo5XF4Xjp0MpS7sb3pFFPa 5moafTrnNTvxUGBDM04aLF8cqjwwhbjYaj20Acg9eQU0soFYDClKAqu9mfZpwd+7FtGqdummT+NkLE Je5GrodyuEztOMlaffvVuLENBoTEmhsNGOBp41iYqbE9zPcJ9MS1DJ0rvImgv3muTMni6WluE/PMlA G8Bw1xFBMfuGUHaUOHV9acOEFsaJHM8tm5cL9Q4euG1jakI5E5R1TGgetTVjgXpB5j3mQ2Pf3RF6JT 4y6m5UCHAePgspKzh99ycSK6R0PB6JMHAPZmQZsfluAKQ4CQBGiqKPHchDzw== X-Developer-Key: i=louis.chauvet@bootlin.com; a=openpgp; fpr=8B7104AE9A272D6693F527F2EC1883F55E0B40A5 X-GND-Sasl: louis.chauvet@bootlin.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Arthur Grillo VKMS has support for YUV formats now. Remove the task from the TODO list. Signed-off-by: Arthur Grillo Signed-off-by: Louis Chauvet --- Documentation/gpu/vkms.rst | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Documentation/gpu/vkms.rst b/Documentation/gpu/vkms.rst index ba04ac7c2167..13b866c3617c 100644 --- a/Documentation/gpu/vkms.rst +++ b/Documentation/gpu/vkms.rst @@ -122,8 +122,7 @@ There's lots of plane features we could add support for: - Scaling. -- Additional buffer formats, especially YUV formats for video like NV12. - Low/high bpp RGB formats would also be interesting. +- Additional buffer formats. Low/high bpp RGB formats would be interesting. - Async updates (currently only possible on cursor plane using the legacy cursor api). From patchwork Mon Mar 4 15:28:19 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Louis Chauvet X-Patchwork-Id: 13580746 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 81BDFC5478C for ; Mon, 4 Mar 2024 15:29:40 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id D764C1122B1; Mon, 4 Mar 2024 15:29:38 +0000 (UTC) Authentication-Results: gabe.freedesktop.org; dkim=pass (2048-bit key; unprotected) header.d=bootlin.com header.i=@bootlin.com header.b="kV3Vg5ij"; dkim-atps=neutral Received: from relay5-d.mail.gandi.net (relay5-d.mail.gandi.net [217.70.183.197]) by gabe.freedesktop.org (Postfix) with ESMTPS id B4D6B1122A7 for ; Mon, 4 Mar 2024 15:29:35 +0000 (UTC) Received: by mail.gandi.net (Postfix) with ESMTPSA id 625D81C0011; Mon, 4 Mar 2024 15:29:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=gm1; t=1709566174; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=Sxj7PD7QU9ATJPEMVZ0jCO8idYJAgbdOpi3aVdMCsmM=; b=kV3Vg5ijL9b5AdnNkmG9kUZ4jn/zrvdgEKB8/rsRl2Dp3Mnj5IOLpuuLdqCJkO4/6Tsgwf rohZUr12EcBNjGKGiN+H492zw4tcJO2KphkVyPyRKRoqvxlpM0pw8Nnp+YdznDOt0os/eA 4iyAsV2r0021vPX2lwYSBHm7Ymc7S5CV67CbUFmHUWh4k+/zj1ln2zq8MgwMNL1kfrAi5v dN44qC5+vnJysmdbAZaRvEry5wiZGRCsOsHlhGEnImjYKXn3QnSidmNSe7ksvrjMQPZOL0 Fr8ZR3QztMjBKSYQs0XZNBeCut0O1ZrxApFnm98bGUwqq2DhPPoqIdoFZCkuXg== From: Louis Chauvet Date: Mon, 04 Mar 2024 16:28:19 +0100 Subject: [PATCH v4 14/14] drm/vkms: Create KUnit tests for YUV conversions MIME-Version: 1.0 Message-Id: <20240304-yuv-v4-14-76beac8e9793@bootlin.com> References: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> In-Reply-To: <20240304-yuv-v4-0-76beac8e9793@bootlin.com> To: Rodrigo Siqueira , Melissa Wen , =?utf-8?q?Ma=C3=ADra_Canal?= , Haneen Mohammed , Daniel Vetter , Maarten Lankhorst , Maxime Ripard , Thomas Zimmermann , David Airlie , arthurgrillo@riseup.net, Jonathan Corbet , pekka.paalanen@haloniitty.fi Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, jeremie.dautheribes@bootlin.com, miquel.raynal@bootlin.com, thomas.petazzoni@bootlin.com, seanpaul@google.com, marcheu@google.com, nicolejadeyee@google.com, Louis Chauvet X-Mailer: b4 0.13.0 X-Developer-Signature: v=1; a=openpgp-sha256; l=10466; i=louis.chauvet@bootlin.com; h=from:subject:message-id; bh=oit4DBZsqYBsCSeCVnB90xL2YrQEqzM2Rsn5P03j1zs=; b=owEBbQKS/ZANAwAIASCtLsZbECziAcsmYgBl5ejNN1MQo+P1mq5+sUn5p5kzGYr35Lao4Xt3vrkl hn+gONyJAjMEAAEIAB0WIQRPj7g/vng8MQxQWQQgrS7GWxAs4gUCZeXozQAKCRAgrS7GWxAs4tRhEA C+8Urz+c3RbOiqiY+106LXtJxOGqN2KIp8qYemSm/SFIJV8SGLVcCLk/07Wuyixeg3gPw6vrc/aSex eKXyNmmKCiI4laJU5Dp9Ci1/HP0njBEQQCTsZtQXjM+DyyBDNZ46FOezgGsgN5dHdN7uJZwYA+8Jqi rJDuHAims+TJ5A8xBmOTzml5wvZWm4PCylvmrTFo6DFKqpWKoMKHrJAzkb1Mt5uU/YYyP9uOxJowPb oSnez51Yt4TxoI9Ldx3ZxihL4/Zvkf5VMXhTO4cUHaVk61tI1WTVC4Sh7LJzjoBS27eot5awr3wdrC NSRT92mPfjZX9OyAWckKPRenTr8/vwCFX3lfqazc9XzvxVNqSrU1crxHSKKr6oQfUY7XOT+yXUggMR OxsIjAR5YNX/8up0lCF3uOgtDu6p41pNTpLRghHW9u8a3eo/ipFfHEo6OGjJN7tX++sAneZ0SLO0Xc 8IRiRJsHL9yque6iqdfXMx2Qq22/NOkpygkgu58aVER48SAjFOKd2Dhk76yLMhuE/LOZQNmw9IU67D ckLhhqwchi95f/lBVq8fubuj82cDrOV1g2T7RLq+eDRPwwIyBJDabhk/852Wy9fnIxQHFrt0U/sV0v Eam6nfIt49N/WDBWvIDdm3Y/AB39OcdERAFyCuhx2Ubu+98gJZ8sj0oUfwRA== X-Developer-Key: i=louis.chauvet@bootlin.com; a=openpgp; fpr=8B7104AE9A272D6693F527F2EC1883F55E0B40A5 X-GND-Sasl: louis.chauvet@bootlin.com X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dri-devel-bounces@lists.freedesktop.org Sender: "dri-devel" From: Arthur Grillo Create KUnit tests to test the conversion between YUV and RGB. Test each conversion and range combination with some common colors. Signed-off-by: Arthur Grillo [Louis Chauvet: fix minor formating issues (whitespace, double line), change expected alpha from 0x0000 to 0xffff, adapt to the new get_conversion_matrix usage] Signed-off-by: Louis Chauvet --- drivers/gpu/drm/vkms/Kconfig | 15 +++ drivers/gpu/drm/vkms/Makefile | 1 + drivers/gpu/drm/vkms/tests/.kunitconfig | 4 + drivers/gpu/drm/vkms/tests/Makefile | 3 + drivers/gpu/drm/vkms/tests/vkms_format_test.c | 158 ++++++++++++++++++++++++++ drivers/gpu/drm/vkms/vkms_formats.c | 5 +- drivers/gpu/drm/vkms/vkms_formats.h | 4 + 7 files changed, 189 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vkms/Kconfig b/drivers/gpu/drm/vkms/Kconfig index b9ecdebecb0b..9b0e1940c14f 100644 --- a/drivers/gpu/drm/vkms/Kconfig +++ b/drivers/gpu/drm/vkms/Kconfig @@ -13,3 +13,18 @@ config DRM_VKMS a VKMS. If M is selected the module will be called vkms. + +config DRM_VKMS_KUNIT_TESTS + tristate "Tests for VKMS" if !KUNIT_ALL_TESTS + depends on DRM_VKMS && KUNIT + default KUNIT_ALL_TESTS + help + This builds unit tests for VKMS. This option is not useful for + distributions or general kernels, but only for kernel + developers working on VKMS. + + For more information on KUnit and unit tests in general, + please refer to the KUnit documentation in + Documentation/dev-tools/kunit/. + + If in doubt, say "N". \ No newline at end of file diff --git a/drivers/gpu/drm/vkms/Makefile b/drivers/gpu/drm/vkms/Makefile index 1b28a6a32948..8d3e46dde635 100644 --- a/drivers/gpu/drm/vkms/Makefile +++ b/drivers/gpu/drm/vkms/Makefile @@ -9,3 +9,4 @@ vkms-y := \ vkms_writeback.o obj-$(CONFIG_DRM_VKMS) += vkms.o +obj-$(CONFIG_DRM_VKMS_KUNIT_TESTS) += tests/ diff --git a/drivers/gpu/drm/vkms/tests/.kunitconfig b/drivers/gpu/drm/vkms/tests/.kunitconfig new file mode 100644 index 000000000000..70e378228cbd --- /dev/null +++ b/drivers/gpu/drm/vkms/tests/.kunitconfig @@ -0,0 +1,4 @@ +CONFIG_KUNIT=y +CONFIG_DRM=y +CONFIG_DRM_VKMS=y +CONFIG_DRM_VKMS_KUNIT_TESTS=y diff --git a/drivers/gpu/drm/vkms/tests/Makefile b/drivers/gpu/drm/vkms/tests/Makefile new file mode 100644 index 000000000000..2d1df668569e --- /dev/null +++ b/drivers/gpu/drm/vkms/tests/Makefile @@ -0,0 +1,3 @@ +# SPDX-License-Identifier: GPL-2.0-only + +obj-$(CONFIG_DRM_VKMS_KUNIT_TESTS) += vkms_format_test.o diff --git a/drivers/gpu/drm/vkms/tests/vkms_format_test.c b/drivers/gpu/drm/vkms/tests/vkms_format_test.c new file mode 100644 index 000000000000..4636b013602f --- /dev/null +++ b/drivers/gpu/drm/vkms/tests/vkms_format_test.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0+ + +#include + +#include +#include +#include + +#include "../../drm_crtc_internal.h" + +#include "../vkms_drv.h" +#include "../vkms_formats.h" + +#define TEST_BUFF_SIZE 50 + +struct yuv_u8_to_argb_u16_case { + enum drm_color_encoding encoding; + enum drm_color_range range; + size_t n_colors; + struct format_pair { + char *name; + struct pixel_yuv_u8 yuv; + struct pixel_argb_u16 argb; + } colors[TEST_BUFF_SIZE]; +}; + +static struct yuv_u8_to_argb_u16_case yuv_u8_to_argb_u16_cases[] = { + { + .encoding = DRM_COLOR_YCBCR_BT601, + .range = DRM_COLOR_YCBCR_FULL_RANGE, + .n_colors = 6, + .colors = { + {"white", {0xff, 0x80, 0x80}, {0xffff, 0xffff, 0xffff, 0xffff}}, + {"gray", {0x80, 0x80, 0x80}, {0xffff, 0x8000, 0x8000, 0x8000}}, + {"black", {0x00, 0x80, 0x80}, {0xffff, 0x0000, 0x0000, 0x0000}}, + {"red", {0x4c, 0x55, 0xff}, {0xffff, 0xffff, 0x0000, 0x0000}}, + {"green", {0x96, 0x2c, 0x15}, {0xffff, 0x0000, 0xffff, 0x0000}}, + {"blue", {0x1d, 0xff, 0x6b}, {0xffff, 0x0000, 0x0000, 0xffff}}, + }, + }, + { + .encoding = DRM_COLOR_YCBCR_BT601, + .range = DRM_COLOR_YCBCR_LIMITED_RANGE, + .n_colors = 6, + .colors = { + {"white", {0xeb, 0x80, 0x80}, {0xffff, 0xffff, 0xffff, 0xffff}}, + {"gray", {0x7e, 0x80, 0x80}, {0xffff, 0x8000, 0x8000, 0x8000}}, + {"black", {0x10, 0x80, 0x80}, {0xffff, 0x0000, 0x0000, 0x0000}}, + {"red", {0x51, 0x5a, 0xf0}, {0xffff, 0xffff, 0x0000, 0x0000}}, + {"green", {0x91, 0x36, 0x22}, {0xffff, 0x0000, 0xffff, 0x0000}}, + {"blue", {0x29, 0xf0, 0x6e}, {0xffff, 0x0000, 0x0000, 0xffff}}, + }, + }, + { + .encoding = DRM_COLOR_YCBCR_BT709, + .range = DRM_COLOR_YCBCR_FULL_RANGE, + .n_colors = 4, + .colors = { + {"white", {0xff, 0x80, 0x80}, {0xffff, 0xffff, 0xffff, 0xffff}}, + {"gray", {0x80, 0x80, 0x80}, {0xffff, 0x8000, 0x8000, 0x8000}}, + {"black", {0x00, 0x80, 0x80}, {0xffff, 0x0000, 0x0000, 0x0000}}, + {"red", {0x36, 0x63, 0xff}, {0xffff, 0xffff, 0x0000, 0x0000}}, + {"green", {0xb6, 0x1e, 0x0c}, {0xffff, 0x0000, 0xffff, 0x0000}}, + {"blue", {0x12, 0xff, 0x74}, {0xffff, 0x0000, 0x0000, 0xffff}}, + }, + }, + { + .encoding = DRM_COLOR_YCBCR_BT709, + .range = DRM_COLOR_YCBCR_LIMITED_RANGE, + .n_colors = 4, + .colors = { + {"white", {0xeb, 0x80, 0x80}, {0xffff, 0xffff, 0xffff, 0xffff}}, + {"gray", {0x7e, 0x80, 0x80}, {0xffff, 0x8000, 0x8000, 0x8000}}, + {"black", {0x10, 0x80, 0x80}, {0xffff, 0x0000, 0x0000, 0x0000}}, + {"red", {0x3f, 0x66, 0xf0}, {0xffff, 0xffff, 0x0000, 0x0000}}, + {"green", {0xad, 0x2a, 0x1a}, {0xffff, 0x0000, 0xffff, 0x0000}}, + {"blue", {0x20, 0xf0, 0x76}, {0xffff, 0x0000, 0x0000, 0xffff}}, + }, + }, + { + .encoding = DRM_COLOR_YCBCR_BT2020, + .range = DRM_COLOR_YCBCR_FULL_RANGE, + .n_colors = 4, + .colors = { + {"white", {0xff, 0x80, 0x80}, {0xffff, 0xffff, 0xffff, 0xffff}}, + {"gray", {0x80, 0x80, 0x80}, {0xffff, 0x8000, 0x8000, 0x8000}}, + {"black", {0x00, 0x80, 0x80}, {0xffff, 0x0000, 0x0000, 0x0000}}, + {"red", {0x43, 0x5c, 0xff}, {0xffff, 0xffff, 0x0000, 0x0000}}, + {"green", {0xad, 0x24, 0x0b}, {0xffff, 0x0000, 0xffff, 0x0000}}, + {"blue", {0x0f, 0xff, 0x76}, {0xffff, 0x0000, 0x0000, 0xffff}}, + }, + }, + { + .encoding = DRM_COLOR_YCBCR_BT2020, + .range = DRM_COLOR_YCBCR_LIMITED_RANGE, + .n_colors = 4, + .colors = { + {"white", {0xeb, 0x80, 0x80}, {0xffff, 0xffff, 0xffff, 0xffff}}, + {"gray", {0x7e, 0x80, 0x80}, {0xffff, 0x8000, 0x8000, 0x8000}}, + {"black", {0x10, 0x80, 0x80}, {0xffff, 0x0000, 0x0000, 0x0000}}, + {"red", {0x4a, 0x61, 0xf0}, {0xffff, 0xffff, 0x0000, 0x0000}}, + {"green", {0xa4, 0x2f, 0x19}, {0xffff, 0x0000, 0xffff, 0x0000}}, + {"blue", {0x1d, 0xf0, 0x77}, {0xffff, 0x0000, 0x0000, 0xffff}}, + }, + }, +}; + +static void vkms_format_test_yuv_u8_to_argb_u16(struct kunit *test) +{ + const struct yuv_u8_to_argb_u16_case *param = test->param_value; + struct pixel_argb_u16 argb; + + for (size_t i = 0; i < param->n_colors; i++) { + const struct format_pair *color = ¶m->colors[i]; + + const struct conversion_matrix *matrix = get_conversion_matrix_to_argb_u16 + (DRM_FORMAT_NV12, param->encoding, param->range); + + argb = argb_u16_from_yuv888(color->yuv.y, color->yuv.u, color->yuv.v, matrix); + + KUNIT_EXPECT_LE_MSG(test, abs_diff(argb.a, color->argb.a), 257, + "On the A channel of the color %s expected 0x%04x, got 0x%04x", + color->name, color->argb.a, argb.a); + KUNIT_EXPECT_LE_MSG(test, abs_diff(argb.r, color->argb.r), 257, + "On the R channel of the color %s expected 0x%04x, got 0x%04x", + color->name, color->argb.r, argb.r); + KUNIT_EXPECT_LE_MSG(test, abs_diff(argb.g, color->argb.g), 257, + "On the G channel of the color %s expected 0x%04x, got 0x%04x", + color->name, color->argb.g, argb.g); + KUNIT_EXPECT_LE_MSG(test, abs_diff(argb.b, color->argb.b), 257, + "On the B channel of the color %s expected 0x%04x, got 0x%04x", + color->name, color->argb.b, argb.b); + } +} + +static void vkms_format_test_yuv_u8_to_argb_u16_case_desc(struct yuv_u8_to_argb_u16_case *t, + char *desc) +{ + snprintf(desc, KUNIT_PARAM_DESC_SIZE, "%s - %s", + drm_get_color_encoding_name(t->encoding), drm_get_color_range_name(t->range)); +} + +KUNIT_ARRAY_PARAM(yuv_u8_to_argb_u16, yuv_u8_to_argb_u16_cases, + vkms_format_test_yuv_u8_to_argb_u16_case_desc); + +static struct kunit_case vkms_format_test_cases[] = { + KUNIT_CASE_PARAM(vkms_format_test_yuv_u8_to_argb_u16, yuv_u8_to_argb_u16_gen_params), + {} +}; + +static struct kunit_suite vkms_format_test_suite = { + .name = "vkms-format", + .test_cases = vkms_format_test_cases, +}; + +kunit_test_suite(vkms_format_test_suite); + +MODULE_LICENSE("GPL"); diff --git a/drivers/gpu/drm/vkms/vkms_formats.c b/drivers/gpu/drm/vkms/vkms_formats.c index d9b70d9b99ef..44d9b9b3bdc3 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.c +++ b/drivers/gpu/drm/vkms/vkms_formats.c @@ -7,6 +7,8 @@ #include #include +#include + #include "vkms_formats.h" /** @@ -185,7 +187,7 @@ static struct pixel_argb_u16 argb_u16_from_RGB565(const u16 *pixel) return out_pixel; } -static struct pixel_argb_u16 argb_u16_from_yuv888(u8 y, u8 cb, u8 cr, +VISIBLE_IF_KUNIT struct pixel_argb_u16 argb_u16_from_yuv888(u8 y, u8 cb, u8 cr, struct conversion_matrix *matrix) { u8 r, g, b; @@ -218,6 +220,7 @@ static struct pixel_argb_u16 argb_u16_from_yuv888(u8 y, u8 cb, u8 cr, return argb_u16_from_u8888(255, r, g, b); } +EXPORT_SYMBOL_IF_KUNIT(argb_u16_from_yuv888); /* * The following functions are read_line function for each pixel format supported by VKMS. diff --git a/drivers/gpu/drm/vkms/vkms_formats.h b/drivers/gpu/drm/vkms/vkms_formats.h index e1d324764b17..21e66a0cac16 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.h +++ b/drivers/gpu/drm/vkms/vkms_formats.h @@ -13,4 +13,8 @@ struct conversion_matrix * get_conversion_matrix_to_argb_u16(u32 format, enum drm_color_encoding encoding, enum drm_color_range range); +#if IS_ENABLED(CONFIG_KUNIT) +struct pixel_argb_u16 argb_u16_from_yuv888(u8 y, u8 cb, u8 cr, struct conversion_matrix *matrix); +#endif + #endif /* _VKMS_FORMATS_H_ */