From patchwork Wed Sep 30 22:59:35 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Heinrich Schuchardt X-Patchwork-Id: 1374756 X-Patchwork-Delegate: agust@denx.de Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=85.214.62.61; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=gmx.de Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; secure) header.d=gmx.net header.i=@gmx.net header.a=rsa-sha256 header.s=badeba3b8450 header.b=LY8z7zXW; dkim-atps=neutral Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4C1sD03Czsz9sTR for ; Thu, 1 Oct 2020 09:00:06 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 9B86D81BF9; Thu, 1 Oct 2020 00:59:57 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=gmx.de Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; secure) header.d=gmx.net header.i=@gmx.net header.b="LY8z7zXW"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 2259D82252; Thu, 1 Oct 2020 00:59:55 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=-2.3 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,FREEMAIL_FROM,RCVD_IN_MSPIKE_H2,SPF_HELO_NONE,URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.2 Received: from mout.gmx.net (mout.gmx.net [212.227.17.22]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 66C0881BD2 for ; Thu, 1 Oct 2020 00:59:51 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=none (p=none dis=none) header.from=gmx.de Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=xypron.glpk@gmx.de DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=gmx.net; s=badeba3b8450; t=1601506790; bh=dpiscBLhasGCrpGtyNKDPoTdo0tupZV3MgE15dNJZZ4=; h=X-UI-Sender-Class:From:To:Cc:Subject:Date; b=LY8z7zXWP1L8fEn71O0TEgYh7ou/6ri28pQIwtCrWF+Z/CTjFmilhWSJ1lA/Klx9c /0FQOUT2DCD541XGqU4VfnHOLGT6ITmt4F8fh8PG5eSieJA7Zngw898gOlbXYOXB9l Z4BiO0KUqEuxP8s1EVSv67+fRTQITRmDng3P9z8s= X-UI-Sender-Class: 01bb95c1-4bf8-414a-932a-4f6e2808ef9c Received: from LT02.fritz.box ([178.202.41.107]) by mail.gmx.com (mrgmx105 [212.227.17.174]) with ESMTPSA (Nemesis) id 1MzhjF-1kau7511qz-00veZa; Thu, 01 Oct 2020 00:59:50 +0200 From: Heinrich Schuchardt To: Anatolij Gustschin Cc: Simon Glass , u-boot@lists.denx.de, Heinrich Schuchardt Subject: [PATCH 1/1] video: support colors in truetype console Date: Thu, 1 Oct 2020 00:59:35 +0200 Message-Id: <20200930225935.256667-1-xypron.glpk@gmx.de> X-Mailer: git-send-email 2.28.0 MIME-Version: 1.0 X-Provags-ID: V03:K1:FM9Pfpmq0FIas/8qhYyKUAMlxt86BMFGX2dKVKJVW2R83X9rXnq aQj2xw0c7RfVN2hRv29EvJRezIv/r162v0SI/nXRRLhGEdPXVpsN4jFy+FwL5pE2KHNCxK8 B1OE5KgcEAhCzLrtxrOA9tRv7c2Crti1xdU0oj34PMFQRyKNwEskqhxseoGb/B8T6Ue9r6Z HbPou847xLV2sjlpti/xw== X-UI-Out-Filterresults: notjunk:1;V03:K0:HjS+92POqa0=:uAif+dwItClc6pZ2LYsxea 1+mNa5GAHy+88WsAlRh7tNzwqU6KZkZ4KruTJpVIcZKDapWrrk5ecL+XyiMxWrmdI9jiChgTf Ku0tyJiNRwSjFCxKYOJdCNvBCvNB52d5RYT26MJLGmgyFtu/VovCaWPByKhkQheOjB85aMTCR HX78IEqi4hPtrGeCrjf2ImbcyfXoOHNiuu1pEELJRiIMoBbC7PlKGmBTaZY73Weqon82W+zq9 Y8N9fxJg9oYWz4MksScS0eE4E9ObZw9x/eYxbVRsjnhv1HFUal/EdPL3eZNV1UUxD1vjQtmLD bWy6R4WHgIYJmCYkf5g1sU7+j9/j2R3IGKYJlURTkRFKMpU7lbGuPLBPLVKWe3jsxxb8HDdxE J89J8himerqgKwo/o7f/e77D2IKEnMQqaSoT48mNut7hvwExLcU/J4tFID3lmAiWU7p/t4Z9b JOEmcmxk8WpYCh9x5ktYvHhjF5Ry0imv73cEZy8LtRqpYByA3mGmO9lT/Gg4Nd99iXdTgCkMo yixQfX90ffYmYagDQehoB0vwPaxKxbAwoP1PtUfV58qudXOkLUTZCb9mIAFP624WKI94dzkkU iJVOGff12/6NXt1AWbJbgsA+eR4QKzH0BuNMPoR3NSTZGARshCgSCJ236co199P7zHt/JjbNy kjmP8fTekPBaQ9+U/Q6dlgH15ePqHzDXCr73jAnc6NtxO+YfesISVfaoM9vYn+w0noA+jXJlj IuBBkKUKGciROqDvZvg5GefxPitjNbNq1qwXkZwXm61N0t/rvh+v1ZW34Pms72r/yUdqLHALM 9PRbS68vCcmi4JK9/IVd7Re2gMC98Wd1vP9WF4eQpT26GD6GLB2n/AUxp0NO/JiFYv6l2BHLi KBRvfa5SbT11o5bjPn1LOtTKr2rhkufgE/ZmftxlbjQIcX/g77BIuWpwFfGOBoYgwm0kk2kDx iJTJlLtiKkdUlGnj5W6F8Wv/Z3YKGs+yrUTv+tstmgQ0lfR36MiwDaC262M3M6b6eeIiPGqh5 I+zPpwMH697qiATKtAPhW2pP4VSvE/pLzzZ+ZBaqx+kzYBzZNh1ob+7rmeUea+0mHqet8TQKf sYCtCikjqeq+4C1mqG9oeV0ohuqMe0n97Rcwsk8BE5zCscCSj+yumTNwLIsHQAkkNAisKEkI+ 37n2hmodAMLrnH6lnqkSX4QAJzrjL65Fcl3UU8x43cYUBN2GxKh8FS46+X3UNlLgNLxXfLCph L/hOwxKsbe6Oz7jsIWYQrnj4Zl/g0SofGv/XTQg== X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.102.3 at phobos.denx.de X-Virus-Status: Clean In the UEFI context we use colored output. When printing truetype letters we have to interpolate the pixel color between the foreground and background color according to the gray value of the font pixel. We could speed up the output a by writing a lookup table in the uclass whenever a color changes but this would impose a burden on all console drivers. So this is not implemented. For testing the sandbox can be used when enabling CONFIG_EFI_SELFTEST. $ ./u-boot -D -l => setenv efi_selftest text output => bootefi selftest This test writes text in all combinations of foreground and background colors to the console. To test 16bit mode modify arch/sandbox/dts/sandbox.dtsi. Set /lcd/log2-depth = <4>; Signed-off-by: Heinrich Schuchardt --- For testing the following patches for the sandbox are needed: [PATCH v2 1/1] sandbox: redefine getc() https://lists.denx.de/pipermail/u-boot/2020-September/428082.html [PATCH 1/1] sandbox: add missing SDL key scan codes https://lists.denx.de/pipermail/u-boot/2020-September/428007.html --- drivers/video/console_truetype.c | 156 ++++++++++++++++++++----------- test/dm/video.c | 6 +- 2 files changed, 104 insertions(+), 58 deletions(-) -- 2.28.0 diff --git a/drivers/video/console_truetype.c b/drivers/video/console_truetype.c index 22b2ea7191..f50bb9df2f 100644 --- a/drivers/video/console_truetype.c +++ b/drivers/video/console_truetype.c @@ -212,8 +212,10 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, struct pos_info *pos; u8 *bits, *data; int advance; - void *start, *end, *line; + void *start, *line, *sync_start, *sync_end; int row, ret; + int bg_r, bg_g, bg_b; + int fg_r, fg_g, fg_b; /* First get some basic metrics about this character */ stbtt_GetCodepointHMetrics(font, ch, &advance, &lsb); @@ -257,82 +259,126 @@ static int console_truetype_putc_xy(struct udevice *dev, uint x, uint y, data = stbtt_GetCodepointBitmapSubpixel(font, priv->scale, priv->scale, x_shift, 0, ch, &width, &height, &xoff, &yoff); - if (!data) - return width_frac; + bits = data; /* Figure out where to write the character in the frame buffer */ - bits = data; - start = vid_priv->fb + y * vid_priv->line_length + - VID_TO_PIXEL(x) * VNBYTES(vid_priv->bpix); + sync_start = vid_priv->fb + y * vid_priv->line_length; + sync_end = sync_start + vc_priv->y_charsize * vid_priv->line_length; + start = sync_start + VID_TO_PIXEL(x) * VNBYTES(vid_priv->bpix); linenum = priv->baseline + yoff; - if (linenum > 0) - start += linenum * vid_priv->line_length; - line = start; + line = start + linenum * vid_priv->line_length; + + /* Decompose foreground and background color */ + switch (vid_priv->bpix) { +#ifdef CONFIG_VIDEO_BPP16 + case VIDEO_BPP16: + bg_r = (vid_priv->colour_bg >> 11) & 0x1f; + bg_g = (vid_priv->colour_bg >> 5) & 0x3f; + bg_b = (vid_priv->colour_bg >> 0) & 0x1f; + + fg_r = (vid_priv->colour_fg >> 11) & 0x1f; + fg_g = (vid_priv->colour_fg >> 5) & 0x3f; + fg_b = (vid_priv->colour_fg >> 0) & 0x1f; + break; +#endif +#ifdef CONFIG_VIDEO_BPP32 + case VIDEO_BPP32: + bg_r = (vid_priv->colour_bg >> 16) & 0xff; + bg_g = (vid_priv->colour_bg >> 8) & 0xff; + bg_b = (vid_priv->colour_bg >> 0) & 0xff; + + fg_r = (vid_priv->colour_fg >> 16) & 0xff; + fg_g = (vid_priv->colour_fg >> 8) & 0xff; + fg_b = (vid_priv->colour_fg >> 0) & 0xff; + break; +#endif + default: + free(data); + return -ENOSYS; + } /* * Write a row at a time, converting the 8bpp image into the colour - * depth of the display. We only expect white-on-black or the reverse - * so the code only handles this simple case. + * depth of the display. */ - for (row = 0; row < height; row++) { - switch (vid_priv->bpix) { + switch (vid_priv->bpix) { #ifdef CONFIG_VIDEO_BPP16 - case VIDEO_BPP16: { - uint16_t *dst = (uint16_t *)line + xoff; + case VIDEO_BPP16: + for (row = 0; row < vc_priv->y_charsize; row++) { + u16 *dst = (u16 *)start; int i; - for (i = 0; i < width; i++) { - int val = *bits; - int out; - - if (vid_priv->colour_bg) - val = 255 - val; - out = val >> 3 | - (val >> 2) << 5 | - (val >> 3) << 11; - if (vid_priv->colour_fg) - *dst++ |= out; - else - *dst++ &= out; - bits++; + for (i = 0; i < xpos; ++i) + *dst++ = vid_priv->colour_bg; + start += vid_priv->line_length; + } + if (data) { + for (row = 0; row < height; row++) { + u16 *dst = (u16 *)line + xoff; + int i; + + for (i = 0; i < width; i++) { + int fg, bg, r, g, b, out; + + /* + * Interpolate between foreground and + * background color. + */ + fg = 1 + *bits++; + bg = 0x101 - fg; + r = (fg_r * fg + bg_r * bg) >> 8; + g = (fg_g * fg + bg_g * bg) >> 8; + b = (fg_b * fg + bg_b * bg) >> 8; + out = b | g << 5 | r << 11; + *dst++ = out; + } + line += vid_priv->line_length; } - end = dst; - break; } + break; #endif #ifdef CONFIG_VIDEO_BPP32 - case VIDEO_BPP32: { - u32 *dst = (u32 *)line + xoff; + case VIDEO_BPP32: + for (row = 0; row < vc_priv->y_charsize; row++) { + u32 *dst = (u32 *)start; int i; - for (i = 0; i < width; i++) { - int val = *bits; - int out; - - if (vid_priv->colour_bg) - val = 255 - val; - out = val | val << 8 | val << 16; - if (vid_priv->colour_fg) - *dst++ |= out; - else - *dst++ &= out; - bits++; + for (i = 0; i < xpos; ++i) + *dst++ = vid_priv->colour_bg; + start += vid_priv->line_length; + } + if (data) { + for (row = 0; row < height; row++) { + u32 *dst = (u32 *)line + xoff; + int i; + + for (i = 0; i < width; i++) { + int fg, bg, r, g, b, out; + + /* + * Interpolate between foreground and + * background color. + */ + fg = 1 + *bits++; + bg = 0x101 - fg; + r = (fg_r * fg + bg_r * bg) >> 8; + g = (fg_g * fg + bg_g * bg) >> 8; + b = (fg_b * fg + bg_b * bg) >> 8; + out = b | g << 8 | r << 16; + *dst++ = out; + } + line += vid_priv->line_length; } - end = dst; - break; } + break; #endif - default: - free(data); - return -ENOSYS; - } - - line += vid_priv->line_length; + default: + break; } - ret = vidconsole_sync_copy(dev, start, line); + ret = vidconsole_sync_copy(dev, sync_start, sync_end); + free(data); if (ret) return ret; - free(data); return width_frac; } diff --git a/test/dm/video.c b/test/dm/video.c index 1af948dca3..dd9da3213e 100644 --- a/test/dm/video.c +++ b/test/dm/video.c @@ -344,7 +344,7 @@ static int dm_test_video_truetype(struct unit_test_state *uts) ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev)); ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); vidconsole_put_string(con, test_string); - ut_asserteq(12237, compress_frame_buffer(uts, dev)); + ut_asserteq(13001, compress_frame_buffer(uts, dev)); return 0; } @@ -365,7 +365,7 @@ static int dm_test_video_truetype_scroll(struct unit_test_state *uts) ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev)); ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); vidconsole_put_string(con, test_string); - ut_asserteq(35030, compress_frame_buffer(uts, dev)); + ut_asserteq(36952, compress_frame_buffer(uts, dev)); return 0; } @@ -386,7 +386,7 @@ static int dm_test_video_truetype_bs(struct unit_test_state *uts) ut_assertok(uclass_get_device(UCLASS_VIDEO, 0, &dev)); ut_assertok(uclass_get_device(UCLASS_VIDEO_CONSOLE, 0, &con)); vidconsole_put_string(con, test_string); - ut_asserteq(29018, compress_frame_buffer(uts, dev)); + ut_asserteq(30747, compress_frame_buffer(uts, dev)); return 0; }