From nobody Sat Dec 11 11:27:10 2021 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 8AE5D18E46C9; Sat, 11 Dec 2021 11:27:10 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (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 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4JB58Z26Hrz4ppw; Sat, 11 Dec 2021 11:27:10 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (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) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 24D36509F; Sat, 11 Dec 2021 11:27:10 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.16.1/8.16.1) with ESMTP id 1BBBRAkV000617; Sat, 11 Dec 2021 11:27:10 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.16.1/8.16.1/Submit) id 1BBBRAvd000616; Sat, 11 Dec 2021 11:27:10 GMT (envelope-from git) Date: Sat, 11 Dec 2021 11:27:10 GMT Message-Id: <202112111127.1BBBRAvd000616@gitrepo.freebsd.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Toomas Soome Subject: git: 6102f43cf060 - main - loader: framebuffer should only be written into List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-src-all@freebsd.org X-BeenThere: dev-commits-src-all@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: tsoome X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 6102f43cf060a592894dcd591c2dfced14581983 Auto-Submitted: auto-generated ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1639222030; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=+wjQWv/3uYFhtPt5ae/iwhUpjjdbrjvXVbnI75XKU9U=; b=ntY+ry9A0Aq+nLwHyUZajq7ud8+WOHKtmqODGEekr8O8ELqoqNIuc5m4ei2z1N3pVcTqJd l7xFMsu5APmjsM/c0MV5bFhg6/lTBCfHVWMaMf6tlOMrr+4KW24RQgsi0CabJ7tYE/I94s kww/OMatV2srPLvSgCJjPgmYgW7mtNVNYjd+dGtR4PY3BhrX4FY4jaq5Pv1tO0strhuzMa tc3T9hk0s8Q9NWHTRV+q5x7eqAvKhR7XDoHdQslBuMSAvKgjtaQYiP/JJ5KuQF3mmi/uTt jcBeLeNANXzlVjSbCKUT2O+Z7fevjXgpgKYaJhcfClaH9yyGTaekhBZBvaTIgA== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1639222030; a=rsa-sha256; cv=none; b=IhNhEcXqh3R0u8pK/9IU1A/VlYFikII4WHboh0WbtreRWIN8GbOYDGMMeIzHlKBPDtLLPf q3RX1CV5q2lDt0gkiiM4J8+tDIxx2P5dtJAYzAfaXN60RohwaqQdZGPRv6AvUG5WuBu8D/ NUY7zKYcEwDJjI3CKYG6H8aelFIfbQc+qWoEPxtj0owb0P0bnazqH88fB4jULfHoLIO1TG VNiGLOvNLRcN9I0NSHktrdC5XaqYi2870+E8KbbrrnWtotBA93AX6GFJoEa3PVb6abLIXm LYF+AOQNZIiLqBIhbuGPJCmTo/TEAUlwSQHTm62Nfnee7zphGkeNZiPZvk/Q7A== ARC-Authentication-Results: i=1; mx1.freebsd.org; none X-ThisMailContainsUnwantedMimeParts: N The branch main has been updated by tsoome: URL: https://cgit.FreeBSD.org/src/commit/?id=6102f43cf060a592894dcd591c2dfced14581983 commit 6102f43cf060a592894dcd591c2dfced14581983 Author: Toomas Soome AuthorDate: 2021-12-06 17:21:58 +0000 Commit: Toomas Soome CommitDate: 2021-12-11 11:25:35 +0000 loader: framebuffer should only be written into Reading from Write Combining memory can be very-very slow. Try to use shadow buffer to avoid such reads. MFC after: 1 month Differential Revision: https://reviews.freebsd.org/D33305 --- stand/common/gfx_fb.c | 152 +++++++++++++++++++++++++++++------------ stand/common/gfx_fb.h | 3 +- stand/efi/loader/framebuffer.c | 3 + stand/i386/libi386/vbe.c | 4 ++ 4 files changed, 115 insertions(+), 47 deletions(-) diff --git a/stand/common/gfx_fb.c b/stand/common/gfx_fb.c index d13a627e1a74..9e703e05c911 100644 --- a/stand/common/gfx_fb.c +++ b/stand/common/gfx_fb.c @@ -741,6 +741,38 @@ gfxfb_blt_video_to_video(uint32_t SourceX, uint32_t SourceY, return (0); } +static void +gfxfb_shadow_fill(uint32_t *BltBuffer, + uint32_t DestinationX, uint32_t DestinationY, + uint32_t Width, uint32_t Height) +{ + uint32_t fbX, fbY; + + if (gfx_state.tg_shadow_fb == NULL) + return; + + fbX = gfx_state.tg_fb.fb_width; + fbY = gfx_state.tg_fb.fb_height; + + if (BltBuffer == NULL) + return; + + if (DestinationX + Width > fbX) + Width = fbX - DestinationX; + + if (DestinationY + Height > fbY) + Height = fbY - DestinationY; + + uint32_t y2 = Height + DestinationY; + for (uint32_t y1 = DestinationY; y1 < y2; y1++) { + uint32_t off = y1 * fbX + DestinationX; + + for (uint32_t x = 0; x < Width; x++) { + gfx_state.tg_shadow_fb[off + x] = *BltBuffer; + } + } +} + int gfxfb_blt(void *BltBuffer, GFXFB_BLT_OPERATION BltOperation, uint32_t SourceX, uint32_t SourceY, @@ -764,6 +796,8 @@ gfxfb_blt(void *BltBuffer, GFXFB_BLT_OPERATION BltOperation, tpl = BS->RaiseTPL(TPL_NOTIFY); switch (BltOperation) { case GfxFbBltVideoFill: + gfxfb_shadow_fill(BltBuffer, DestinationX, + DestinationY, Width, Height); status = gop->Blt(gop, BltBuffer, EfiBltVideoFill, SourceX, SourceY, DestinationX, DestinationY, Width, Height, Delta); @@ -815,6 +849,8 @@ gfxfb_blt(void *BltBuffer, GFXFB_BLT_OPERATION BltOperation, switch (BltOperation) { case GfxFbBltVideoFill: + gfxfb_shadow_fill(BltBuffer, DestinationX, DestinationY, + Width, Height); rv = gfxfb_blt_fill(BltBuffer, DestinationX, DestinationY, Width, Height); break; @@ -984,7 +1020,6 @@ gfx_fb_fill(void *arg, const teken_rect_t *r, teken_char_t c, static void gfx_fb_cursor_draw(teken_gfx_t *state, const teken_pos_t *pos, bool on) { - unsigned x, y, width, height; const uint8_t *glyph; teken_pos_t p; int idx; @@ -998,42 +1033,6 @@ gfx_fb_cursor_draw(teken_gfx_t *state, const teken_pos_t *pos, bool on) if (idx >= state->tg_tp.tp_col * state->tg_tp.tp_row) return; - width = state->tg_font.vf_width; - height = state->tg_font.vf_height; - x = state->tg_origin.tp_col + p.tp_col * width; - y = state->tg_origin.tp_row + p.tp_row * height; - - /* - * Save original display content to preserve image data. - */ - if (on) { - if (state->tg_cursor_image == NULL || - state->tg_cursor_size != width * height * 4) { - free(state->tg_cursor_image); - state->tg_cursor_size = width * height * 4; - state->tg_cursor_image = malloc(state->tg_cursor_size); - } - if (state->tg_cursor_image != NULL) { - if (gfxfb_blt(state->tg_cursor_image, - GfxFbBltVideoToBltBuffer, x, y, 0, 0, - width, height, 0) != 0) { - free(state->tg_cursor_image); - state->tg_cursor_image = NULL; - } - } - } else { - /* - * Restore display from tg_cursor_image. - * If there is no image, restore char from screen_buffer. - */ - if (state->tg_cursor_image != NULL && - gfxfb_blt(state->tg_cursor_image, GfxFbBltBufferToVideo, - 0, 0, x, y, width, height, 0) == 0) { - state->tg_cursor = p; - return; - } - } - glyph = font_lookup(&state->tg_font, screen_buffer[idx].c, &screen_buffer[idx].a); gfx_bitblt_bitmap(state, glyph, &screen_buffer[idx].a, 0xff, on); @@ -1110,19 +1109,62 @@ gfx_fb_copy_area(teken_gfx_t *state, const teken_rect_t *s, const teken_pos_t *d) { uint32_t sx, sy, dx, dy, width, height; + uint32_t pitch, bytes; + int step; width = state->tg_font.vf_width; height = state->tg_font.vf_height; - sx = state->tg_origin.tp_col + s->tr_begin.tp_col * width; - sy = state->tg_origin.tp_row + s->tr_begin.tp_row * height; - dx = state->tg_origin.tp_col + d->tp_col * width; - dy = state->tg_origin.tp_row + d->tp_row * height; + sx = s->tr_begin.tp_col * width; + sy = s->tr_begin.tp_row * height; + dx = d->tp_col * width; + dy = d->tp_row * height; width *= (s->tr_end.tp_col - s->tr_begin.tp_col + 1); - (void) gfxfb_blt(NULL, GfxFbBltVideoToVideo, sx, sy, dx, dy, + /* + * With no shadow fb, use video to video copy. + */ + if (state->tg_shadow_fb == NULL) { + (void) gfxfb_blt(NULL, GfxFbBltVideoToVideo, + sx + state->tg_origin.tp_col, + sy + state->tg_origin.tp_row, + dx + state->tg_origin.tp_col, + dy + state->tg_origin.tp_row, width, height, 0); + return; + } + + /* + * With shadow fb, we need to copy data on both shadow and video, + * to preserve the consistency. We only read data from shadow fb. + */ + + step = 1; + pitch = state->tg_fb.fb_width; + bytes = width * sizeof (*state->tg_shadow_fb); + + /* + * To handle overlapping areas, set up reverse copy here. + */ + if (dy * pitch + dx > sy * pitch + sx) { + sy += height; + dy += height; + step = -step; + } + + while (height-- > 0) { + uint32_t *source = &state->tg_shadow_fb[sy * pitch + sx]; + uint32_t *destination = &state->tg_shadow_fb[dy * pitch + dx]; + + bcopy(source, destination, bytes); + (void) gfxfb_blt(destination, GfxFbBltBufferToVideo, + 0, 0, dx + state->tg_origin.tp_col, + dy + state->tg_origin.tp_row, width, 1, 0); + + sy += step; + dy += step; + } } static void @@ -1303,13 +1345,32 @@ gfx_fb_cons_display(uint32_t x, uint32_t y, uint32_t width, uint32_t height, void *data) { #if defined(EFI) - EFI_GRAPHICS_OUTPUT_BLT_PIXEL *buf; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL *buf, *p; #else - struct paletteentry *buf; + struct paletteentry *buf, *p; #endif size_t size; - size = width * height * sizeof(*buf); + /* + * If we do have shadow fb, we will use shadow to render data, + * and copy shadow to video. + */ + if (gfx_state.tg_shadow_fb != NULL) { + uint32_t pitch = gfx_state.tg_fb.fb_width; + + /* Copy rectangle line by line. */ + p = data; + for (uint32_t sy = 0; sy < height; sy++) { + buf = (void *)(gfx_state.tg_shadow_fb + + (y - gfx_state.tg_origin.tp_row) * pitch + + x - gfx_state.tg_origin.tp_col); + bitmap_cpy(buf, &p[sy * width], width); + (void) gfxfb_blt(buf, GfxFbBltBufferToVideo, + 0, 0, x, y, width, 1, 0); + y++; + } + return; + } /* * Common data to display is glyph, use preallocated @@ -1318,6 +1379,7 @@ gfx_fb_cons_display(uint32_t x, uint32_t y, uint32_t width, uint32_t height, if (gfx_state.tg_glyph_size != GlyphBufferSize) (void) allocate_glyphbuffer(width, height); + size = width * height * sizeof(*buf); if (size == GlyphBufferSize) buf = GlyphBuffer; else diff --git a/stand/common/gfx_fb.h b/stand/common/gfx_fb.h index 89b060a02cf9..0a2bc966d445 100644 --- a/stand/common/gfx_fb.h +++ b/stand/common/gfx_fb.h @@ -210,14 +210,13 @@ typedef struct teken_gfx { teken_t tg_teken; /* Teken core */ teken_pos_t tg_cursor; /* Where cursor was drawn */ bool tg_cursor_visible; - uint8_t *tg_cursor_image; /* Memory for cursor */ - size_t tg_cursor_size; teken_pos_t tg_tp; /* Terminal dimensions */ teken_pos_t tg_origin; /* Point of origin in pixels */ uint8_t *tg_glyph; /* Memory for glyph */ size_t tg_glyph_size; struct vt_font tg_font; struct gen_fb tg_fb; + uint32_t *tg_shadow_fb; /* units of 4 bytes */ teken_funcs_t *tg_functions; void *tg_private; bool tg_kernel_supported; /* Loaded kernel is supported */ diff --git a/stand/efi/loader/framebuffer.c b/stand/efi/loader/framebuffer.c index adb9dfb62cee..03752b77a24e 100644 --- a/stand/efi/loader/framebuffer.c +++ b/stand/efi/loader/framebuffer.c @@ -622,6 +622,9 @@ efi_find_framebuffer(teken_gfx_t *gfx_state) gfx_state->tg_fb.fb_bpp = fls(efifb.fb_mask_red | efifb.fb_mask_green | efifb.fb_mask_blue | efifb.fb_mask_reserved); + free(gfx_state->tg_shadow_fb); + gfx_state->tg_shadow_fb = malloc(efifb.fb_height * efifb.fb_width * + sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL)); return (0); } diff --git a/stand/i386/libi386/vbe.c b/stand/i386/libi386/vbe.c index ef4daffa8380..cd90e5d6daed 100644 --- a/stand/i386/libi386/vbe.c +++ b/stand/i386/libi386/vbe.c @@ -709,6 +709,10 @@ vbe_set_mode(int modenum) gfx_state.tg_fb.fb_width = mi.XResolution; gfx_state.tg_fb.fb_bpp = mi.BitsPerPixel; + free(gfx_state.tg_shadow_fb); + gfx_state.tg_shadow_fb = malloc(mi.YResolution * mi.XResolution * + sizeof(struct paletteentry)); + /* Bytes per pixel */ bpp = roundup2(mi.BitsPerPixel, NBBY) / NBBY;