Received: by 2002:a05:7412:98c1:b0:fa:551:50a7 with SMTP id kc1csp251332rdb; Fri, 5 Jan 2024 08:38:40 -0800 (PST) X-Google-Smtp-Source: AGHT+IFhRufiNCMYVxhMzbecNeraFLSVgxbr4VCaXbWrY514V1WV6fqLAY2+00u6k5invpQN+rY4 X-Received: by 2002:a05:620a:1115:b0:781:84ad:26d5 with SMTP id o21-20020a05620a111500b0078184ad26d5mr2465923qkk.129.1704472719702; Fri, 05 Jan 2024 08:38:39 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1704472719; cv=none; d=google.com; s=arc-20160816; b=cTbqYz8TOu4jMdPAEEyH3BAjc5do5Y9ASfBubUKFUl7XuovtIKVCPeUyzVbUlwhp1w 0ZLI3cZyxH6jyZRa7o/F0yFsMunfiEWFSTFjfzWP8QvKs8FGSamsJOMYl39yOEHasBc0 U/9kxxamXUF4r2V7VGP4bI+OEt6n2JSQQ7AykhP/pfMBOyjZmZ1e2Eb3Rnf/pJv+rt0D AqVPmg+5uHlT/tMPDn/eHwtaRdWiTsYS4mzeTJbplTfy8TTvaqR0DXs4IDOikRO6HZEE 0jLtjj1XiEzisAMvKY8ti9jlddPGEfowgBoOkc68CBAj8f6twDj58EL0RSOigB7lgKH4 Q5RA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=cc:to:in-reply-to:references:message-id:content-transfer-encoding :mime-version:list-unsubscribe:list-subscribe:list-id:precedence :subject:date:from:dkim-signature; bh=2BQZejR0Od3A56BzwinwI/GWtu6ZMztyEtgdftWN1Hk=; fh=e2pLjgUlBXjelzqkDvkFjOkj11JaHJ4/Nmp/XhAV6n0=; b=D3zJzooTQ8Mn1WPco21+gh9bq1bozxh6h5bnN/Pb0uAmDiOoQPprgOpqnZReB8rKUH yifl5wHyzbf3Luo8LCBetNYOReaf1U2zJEc4kurm4rWoxjdamiWuvIHV1AHjj1j+EfBO 9K3+yjIsl4/rnk9I4KOJtAA01gRgc49VHi5+hNSU+3HlKpgSaeIxDC40ycVkbhkzRADP XVbz2NU3x2uGziO1h9O5yRmILu8aNJdKtbtHC4yaVWe1ufacbMJmGf0HIsXrq0jul820 pxByOaTHoQLOkBECNJh1tkVQimN7jPiAtz8mu/KedGPU1Ldt/vToFVipCFFs29hDlNrS hb1Q== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@riseup.net header.s=squak header.b=ANDxWxTP; spf=pass (google.com: domain of linux-kernel+bounces-18073-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-18073-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=riseup.net Return-Path: Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [2604:1380:45d1:ec00::1]) by mx.google.com with ESMTPS id m22-20020a05620a24d600b00781935ddd47si2111368qkn.402.2024.01.05.08.38.39 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 05 Jan 2024 08:38:39 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-18073-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) client-ip=2604:1380:45d1:ec00::1; Authentication-Results: mx.google.com; dkim=pass header.i=@riseup.net header.s=squak header.b=ANDxWxTP; spf=pass (google.com: domain of linux-kernel+bounces-18073-linux.lists.archive=gmail.com@vger.kernel.org designates 2604:1380:45d1:ec00::1 as permitted sender) smtp.mailfrom="linux-kernel+bounces-18073-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=riseup.net Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id 681161C21B36 for ; Fri, 5 Jan 2024 16:38:39 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id A450735EEC; Fri, 5 Jan 2024 16:37:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=riseup.net header.i=@riseup.net header.b="ANDxWxTP" X-Original-To: linux-kernel@vger.kernel.org Received: from mx1.riseup.net (mx1.riseup.net [198.252.153.129]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 8658035EE9; Fri, 5 Jan 2024 16:37:33 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=riseup.net Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=riseup.net Received: from fews01-sea.riseup.net (fews01-sea-pn.riseup.net [10.0.1.109]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx1.riseup.net (Postfix) with ESMTPS id 4T68JD4GCrzDr8p; Fri, 5 Jan 2024 16:37:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=riseup.net; s=squak; t=1704472653; bh=rLLFxvAwa19v1EUxUV7GhxMebVThqHcOQfYtoRNhJ6Q=; h=From:Date:Subject:References:In-Reply-To:To:Cc:From; b=ANDxWxTPEdnGCSELEPCXI9TynjixksQtG9EilPtTbGz78pOV6QDWY/gEElFgvKnAT Jbn0Wk9uPbqjeFDbAjHid0p63ujbsQlOVfQJqWTI91ssA7nN5QqPBFSPxUHBU8sT0g 60hASPu1jTTHXVJjVM02nXlzu0E61vo3CcZbDgHQ= X-Riseup-User-ID: 6B4ED7332468E6478840368A03A9162AC095E5B8A7792D2FD0EB10BB9FB8CD53 Received: from [127.0.0.1] (localhost [127.0.0.1]) by fews01-sea.riseup.net (Postfix) with ESMTPSA id 4T68J72v4hzJp2K; Fri, 5 Jan 2024 16:37:27 +0000 (UTC) From: Arthur Grillo Date: Fri, 05 Jan 2024 13:35:06 -0300 Subject: [PATCH 5/7] drm/vkms: Add YUV support Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20240105-vkms-yuv-v1-5-34c4cd3455e0@riseup.net> References: <20240105-vkms-yuv-v1-0-34c4cd3455e0@riseup.net> In-Reply-To: <20240105-vkms-yuv-v1-0-34c4cd3455e0@riseup.net> To: Daniel Vetter , David Airlie , Haneen Mohammed , Harry Wentland , Jonathan Corbet , Maarten Lankhorst , Maxime Ripard , =?utf-8?q?Ma=C3=ADra_Canal?= , Melissa Wen , Rodrigo Siqueira , Thomas Zimmermann Cc: dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, linux-doc@vger.kernel.org, Arthur Grillo Add support to the YUV formats bellow: - NV12 - NV16 - NV24 - NV21 - NV61 - NV42 - YUV420 - YUV422 - YUV444 - YVU420 - YVU422 - YVU444 The conversion matrices of each encoding and range were obtained by rounding the values of the original conversion matrices multiplied by 2^8. This is done to avoid the use of fixed point operations. Signed-off-by: Arthur Grillo --- drivers/gpu/drm/vkms/vkms_formats.c | 151 ++++++++++++++++++++++++++++++++++++ drivers/gpu/drm/vkms/vkms_plane.c | 14 +++- 2 files changed, 164 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/vkms/vkms_formats.c b/drivers/gpu/drm/vkms/vkms_formats.c index 098ed16f2104..b654b6661a20 100644 --- a/drivers/gpu/drm/vkms/vkms_formats.c +++ b/drivers/gpu/drm/vkms/vkms_formats.c @@ -119,6 +119,141 @@ static void RGB565_to_argb_u16(u8 **src_pixels, struct pixel_argb_u16 *out_pixel out_pixel->b = drm_fixp2int_round(drm_fixp_mul(fp_b, fp_rb_ratio)); } +struct pixel_yuv_u8 { + u8 y, u, v; +}; + +static void ycbcr2rgb(const s16 m[3][3], u8 y, u8 cb, u8 cr, u8 y_offset, u8 *r, u8 *g, u8 *b) +{ + s32 y_16, cb_16, cr_16; + s32 r_16, g_16, b_16; + + y_16 = y - y_offset; + cb_16 = cb - 128; + cr_16 = cr - 128; + + r_16 = m[0][0] * y_16 + m[0][1] * cb_16 + m[0][2] * cr_16; + g_16 = m[1][0] * y_16 + m[1][1] * cb_16 + m[1][2] * cr_16; + b_16 = m[2][0] * y_16 + m[2][1] * cb_16 + m[2][2] * cr_16; + + *r = clamp(r_16, 0, 0xffff) >> 8; + *g = clamp(g_16, 0, 0xffff) >> 8; + *b = clamp(b_16, 0, 0xffff) >> 8; +} + +static void yuv_u8_to_argb_u16(struct pixel_argb_u16 *argb_u16, const struct pixel_yuv_u8 *yuv_u8, + enum drm_color_encoding encoding, enum drm_color_range range) +{ + static const s16 bt601_full[3][3] = { + {256, 0, 359}, + {256, -88, -183}, + {256, 454, 0}, + }; + static const s16 bt601[3][3] = { + {298, 0, 409}, + {298, -100, -208}, + {298, 516, 0}, + }; + static const s16 rec709_full[3][3] = { + {256, 0, 408}, + {256, -48, -120}, + {256, 476, 0 }, + }; + static const s16 rec709[3][3] = { + {298, 0, 459}, + {298, -55, -136}, + {298, 541, 0}, + }; + static const s16 bt2020_full[3][3] = { + {256, 0, 377}, + {256, -42, -146}, + {256, 482, 0}, + }; + static const s16 bt2020[3][3] = { + {298, 0, 430}, + {298, -48, -167}, + {298, 548, 0}, + }; + + u8 r = 0; + u8 g = 0; + u8 b = 0; + bool full = range == DRM_COLOR_YCBCR_FULL_RANGE; + unsigned int y_offset = full ? 0 : 16; + + switch (encoding) { + case DRM_COLOR_YCBCR_BT601: + ycbcr2rgb(full ? bt601_full : bt601, + yuv_u8->y, yuv_u8->u, yuv_u8->v, y_offset, &r, &g, &b); + break; + case DRM_COLOR_YCBCR_BT709: + ycbcr2rgb(full ? rec709_full : rec709, + yuv_u8->y, yuv_u8->u, yuv_u8->v, y_offset, &r, &g, &b); + break; + case DRM_COLOR_YCBCR_BT2020: + ycbcr2rgb(full ? bt2020_full : bt2020, + yuv_u8->y, yuv_u8->u, yuv_u8->v, y_offset, &r, &g, &b); + break; + default: + pr_warn_once("Not supported color encoding\n"); + break; + } + + argb_u16->r = r * 257; + argb_u16->g = g * 257; + argb_u16->b = b * 257; +} + +static void semi_planar_yuv_to_argb_u16(u8 **src_pixels, struct pixel_argb_u16 *out_pixel, + enum drm_color_encoding encoding, + enum drm_color_range range) +{ + struct pixel_yuv_u8 yuv_u8; + + yuv_u8.y = src_pixels[0][0]; + yuv_u8.u = src_pixels[1][0]; + yuv_u8.v = src_pixels[1][1]; + + yuv_u8_to_argb_u16(out_pixel, &yuv_u8, encoding, range); +} + +static void semi_planar_yvu_to_argb_u16(u8 **src_pixels, struct pixel_argb_u16 *out_pixel, + enum drm_color_encoding encoding, + enum drm_color_range range) +{ + struct pixel_yuv_u8 yuv_u8; + + yuv_u8.y = src_pixels[0][0]; + yuv_u8.v = src_pixels[1][0]; + yuv_u8.u = src_pixels[1][1]; + + yuv_u8_to_argb_u16(out_pixel, &yuv_u8, encoding, range); +} + +static void planar_yuv_to_argb_u16(u8 **src_pixels, struct pixel_argb_u16 *out_pixel, + enum drm_color_encoding encoding, enum drm_color_range range) +{ + struct pixel_yuv_u8 yuv_u8; + + yuv_u8.y = src_pixels[0][0]; + yuv_u8.u = src_pixels[1][0]; + yuv_u8.v = src_pixels[2][0]; + + yuv_u8_to_argb_u16(out_pixel, &yuv_u8, encoding, range); +} + +static void planar_yvu_to_argb_u16(u8 **src_pixels, struct pixel_argb_u16 *out_pixel, + enum drm_color_encoding encoding, enum drm_color_range range) +{ + struct pixel_yuv_u8 yuv_u8; + + yuv_u8.y = src_pixels[0][0]; + yuv_u8.v = src_pixels[1][0]; + yuv_u8.u = src_pixels[2][0]; + + yuv_u8_to_argb_u16(out_pixel, &yuv_u8, encoding, range); +} + /** * vkms_compose_row - compose a single row of a plane * @stage_buffer: output line with the composed pixels @@ -267,6 +402,22 @@ void *get_pixel_conversion_function(u32 format) return &XRGB16161616_to_argb_u16; case DRM_FORMAT_RGB565: return &RGB565_to_argb_u16; + case DRM_FORMAT_NV12: + case DRM_FORMAT_NV16: + case DRM_FORMAT_NV24: + return &semi_planar_yuv_to_argb_u16; + case DRM_FORMAT_NV21: + case DRM_FORMAT_NV61: + case DRM_FORMAT_NV42: + return &semi_planar_yvu_to_argb_u16; + case DRM_FORMAT_YUV420: + case DRM_FORMAT_YUV422: + case DRM_FORMAT_YUV444: + return &planar_yuv_to_argb_u16; + case DRM_FORMAT_YVU420: + case DRM_FORMAT_YVU422: + case DRM_FORMAT_YVU444: + return &planar_yvu_to_argb_u16; default: return NULL; } diff --git a/drivers/gpu/drm/vkms/vkms_plane.c b/drivers/gpu/drm/vkms/vkms_plane.c index e87c80575b7d..932736fc3ee9 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 * -- 2.43.0