fix: LVGL rendering for 16bpp framebuffers (HyperV compatibility)
continuous-integration/drone/push Build is failing
continuous-integration/drone/push Build is failing
The LVGL flush callback assumed 32bpp (4-byte stride, direct pixel copy), causing corrupted output on hypervisors that fall back to 16bpp modes (e.g. HyperV at 1600x1200x16). - lvgl.pas: Make lvgl_flush_cb BPP-aware; add ARGB8888->RGB565 conversion path for 16bpp, keep direct copy for 32bpp. Replace static lv_buf1 array (hardcoded 1600px wide) with kalloc'd buffer sized to actual screen width. - doublebuffer.pas: Fix allocateBackBuffer size from (W*H*BPP) to (W*H*BPP) div 8 to get correct byte count. - vesa.pas: Account for BPP in allocateVESAFrameBuffer page range calculation to avoid under-mapping at higher BPP/resolutions. - Removed the initialization of console in kernel.pas as this will cause issues on some systems that don't expect to need to allocate the textmode buffer.
This commit is contained in:
1 parent
6f50b053b7
commit
be4b482bde
4 files changed
+42
-16
No files matched your search
@@ -32,8 +32,7 @@ implementation
|
|||||||
function allocateBackBuffer(Width : uint32; Height : uint32; BitsPerPixel : uint8) : uint64;
|
function allocateBackBuffer(Width : uint32; Height : uint32; BitsPerPixel : uint8) : uint64;
|
||||||
begin
|
begin
|
||||||
tracer.push_trace('doublebuffer.allocateBackBuffer.enter');
|
tracer.push_trace('doublebuffer.allocateBackBuffer.enter');
|
||||||
//This doesn't currently work... Needs a rework of lmemorymanager
|
allocateBackBuffer:= uint64(klalloc((Width * Height * BitsPerPixel) div 8));
|
||||||
allocateBackBuffer:= uint64(klalloc((Width * Height) * BitsPerPixel));
|
|
||||||
tracer.push_trace('doublebuffer.allocateBackBuffer.exit');
|
tracer.push_trace('doublebuffer.allocateBackBuffer.exit');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|||||||
@@ -1725,7 +1725,8 @@ const
|
|||||||
LV_BUF_LINES = 120;
|
LV_BUF_LINES = 120;
|
||||||
|
|
||||||
var
|
var
|
||||||
lv_buf1: array[0..1600*LV_BUF_LINES-1] of lv_color_t;
|
lv_buf1: pointer;
|
||||||
|
lv_buf1_size: uint32;
|
||||||
|
|
||||||
{ ============================================================
|
{ ============================================================
|
||||||
Color helper
|
Color helper
|
||||||
@@ -1740,25 +1741,47 @@ end;
|
|||||||
|
|
||||||
{ ============================================================
|
{ ============================================================
|
||||||
Flush callback — copies LVGL render buffer to video back buffer
|
Flush callback — copies LVGL render buffer to video back buffer
|
||||||
|
Handles 32bpp (direct copy) and 16bpp (ARGB8888 -> RGB565).
|
||||||
============================================================ }
|
============================================================ }
|
||||||
procedure lvgl_flush_cb(disp: Plv_display; area: Plv_area; color_p: Plv_color); cdecl;
|
procedure lvgl_flush_cb(disp: Plv_display; area: Plv_area; color_p: Plv_color); cdecl;
|
||||||
var
|
var
|
||||||
y, x, area_w: sint32;
|
y, x, area_w: sint32;
|
||||||
src: puint32;
|
src: puint32;
|
||||||
dst: puint32;
|
dst32: puint32;
|
||||||
|
dst16: puint16;
|
||||||
fb_w: uint32;
|
fb_w: uint32;
|
||||||
|
bpp: uint8;
|
||||||
|
pixel: uint32;
|
||||||
|
r, g, b: uint8;
|
||||||
begin
|
begin
|
||||||
fb_w := video.backBufferWidth;
|
fb_w := video.backBufferWidth;
|
||||||
|
bpp := video.backBufferBpp;
|
||||||
area_w := (area^.x2 - area^.x1) + 1;
|
area_w := (area^.x2 - area^.x1) + 1;
|
||||||
src := puint32(color_p);
|
src := puint32(color_p);
|
||||||
|
|
||||||
|
if bpp >= 32 then begin
|
||||||
|
{ 32bpp: direct copy, 4 bytes per pixel }
|
||||||
for y := area^.y1 to area^.y2 do begin
|
for y := area^.y1 to area^.y2 do begin
|
||||||
dst := puint32(video.backBufferLocation + uint32((y * sint32(fb_w) + area^.x1) * 4));
|
dst32 := puint32(video.backBufferLocation + uint32((y * sint32(fb_w) + area^.x1) * 4));
|
||||||
for x := 0 to area_w - 1 do begin
|
for x := 0 to area_w - 1 do begin
|
||||||
dst[x] := src[x];
|
dst32[x] := src[x];
|
||||||
end;
|
end;
|
||||||
src := puint32(uint32(src) + uint32(area_w * 4));
|
src := puint32(uint32(src) + uint32(area_w * 4));
|
||||||
end;
|
end;
|
||||||
|
end else if bpp = 16 then begin
|
||||||
|
{ 16bpp: convert ARGB8888 -> RGB565, 2 bytes per pixel }
|
||||||
|
for y := area^.y1 to area^.y2 do begin
|
||||||
|
dst16 := puint16(video.backBufferLocation + uint32((y * sint32(fb_w) + area^.x1) * 2));
|
||||||
|
for x := 0 to area_w - 1 do begin
|
||||||
|
pixel := src[x];
|
||||||
|
b := pixel and $FF;
|
||||||
|
g := (pixel shr 8) and $FF;
|
||||||
|
r := (pixel shr 16) and $FF;
|
||||||
|
dst16[x] := uint16(((uint16(r) shr 3) shl 11) or ((uint16(g) shr 2) shl 5) or (uint16(b) shr 3));
|
||||||
|
end;
|
||||||
|
src := puint32(uint32(src) + uint32(area_w * 4));
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
lv_display_flush_ready(disp);
|
lv_display_flush_ready(disp);
|
||||||
end;
|
end;
|
||||||
@@ -1852,11 +1875,15 @@ begin
|
|||||||
{ Register log callback }
|
{ Register log callback }
|
||||||
lv_log_register_print_cb(@lvgl_log_cb);
|
lv_log_register_print_cb(@lvgl_log_cb);
|
||||||
|
|
||||||
|
{ Allocate LVGL render buffer dynamically (1/10th of screen) }
|
||||||
|
lv_buf1_size := screen_w * LV_BUF_LINES * SizeOf(lv_color_t);
|
||||||
|
lv_buf1 := pointer(kalloc(lv_buf1_size));
|
||||||
|
|
||||||
{ Create display }
|
{ Create display }
|
||||||
disp := lv_display_create(sint32(screen_w), sint32(screen_h));
|
disp := lv_display_create(sint32(screen_w), sint32(screen_h));
|
||||||
lv_display_set_flush_cb(disp, @lvgl_flush_cb);
|
lv_display_set_flush_cb(disp, @lvgl_flush_cb);
|
||||||
lv_display_set_buffers(disp, @lv_buf1[0], nil,
|
lv_display_set_buffers(disp, lv_buf1, nil,
|
||||||
SizeOf(lv_buf1), LV_DISPLAY_RENDER_MODE_PARTIAL);
|
lv_buf1_size, LV_DISPLAY_RENDER_MODE_PARTIAL);
|
||||||
|
|
||||||
{ Create mouse input device with read callback }
|
{ Create mouse input device with read callback }
|
||||||
mouse_indev := lv_indev_create;
|
mouse_indev := lv_indev_create;
|
||||||
|
|||||||
@@ -32,22 +32,24 @@ implementation
|
|||||||
uses
|
uses
|
||||||
VESA8, VESA16, VESA24, VESA32;
|
VESA8, VESA16, VESA24, VESA32;
|
||||||
|
|
||||||
procedure allocateVESAFrameBuffer(Address : uint32; Width : uint32; Height : uint32);
|
procedure allocateVESAFrameBuffer(Address : uint32; Width : uint32; Height : uint32; BitsPerPixel : uint8);
|
||||||
var
|
var
|
||||||
LowerAddress, UpperAddress : uint32;
|
LowerAddress, UpperAddress : uint32;
|
||||||
Block : uint32;
|
Block : uint32;
|
||||||
|
FrameBufferSize : uint32;
|
||||||
|
|
||||||
begin
|
begin
|
||||||
tracer.push_trace('VESA.allocateFrameBuffer.enter');
|
tracer.push_trace('VESA.allocateFrameBuffer.enter');
|
||||||
|
FrameBufferSize := (Width * Height * BitsPerPixel) div 8;
|
||||||
LowerAddress:= ((Address) SHR 22)-1;
|
LowerAddress:= ((Address) SHR 22)-1;
|
||||||
UpperAddress:= ((Address + (Width * Height)) SHR 22)+1;
|
UpperAddress:= ((Address + FrameBufferSize) SHR 22)+1;
|
||||||
For Block:=LowerAddress to UpperAddress do begin
|
For Block:=LowerAddress to UpperAddress do begin
|
||||||
kpalloc(Block SHL 22);
|
kpalloc(Block SHL 22);
|
||||||
end;
|
end;
|
||||||
tracer.push_trace('VESA.allocateFrameBuffer.exit');
|
tracer.push_trace('VESA.allocateFrameBuffer.exit');
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure initVESAFrameBuffer(VideoBuffer : PVideoBuffer; Location : uint64; Width : uint32; Height : uint32; BitsPerPixel : uint8);
|
procedure initVESAFrameBuffer(VideoBuffer : PVideoBuffer; Location : uint64; Width : uint32; Height : uint32; BitsPerPixel : uint8; Pitch : uint32);
|
||||||
begin
|
begin
|
||||||
tracer.push_trace('VESA.initVESAFrameBuffer.enter');
|
tracer.push_trace('VESA.initVESAFrameBuffer.enter');
|
||||||
if not(VideoBuffer^.Initialized) then begin
|
if not(VideoBuffer^.Initialized) then begin
|
||||||
@@ -55,7 +57,7 @@ begin
|
|||||||
VideoBuffer^.BitsPerPixel:= BitsPerPixel;
|
VideoBuffer^.BitsPerPixel:= BitsPerPixel;
|
||||||
VideoBuffer^.Width:= Width;
|
VideoBuffer^.Width:= Width;
|
||||||
VideoBuffer^.Height:= Height;
|
VideoBuffer^.Height:= Height;
|
||||||
allocateVESAFrameBuffer(VideoBuffer^.Location, VideoBuffer^.Width, VideoBuffer^.Height);
|
allocateVESAFrameBuffer(VideoBuffer^.Location, VideoBuffer^.Width, VideoBuffer^.Height, BitsPerPixel);
|
||||||
if VideoBuffer^.Location <> 0 then
|
if VideoBuffer^.Location <> 0 then
|
||||||
VideoBuffer^.Initialized:= True;
|
VideoBuffer^.Initialized:= True;
|
||||||
end;
|
end;
|
||||||
@@ -65,7 +67,7 @@ end;
|
|||||||
function enable(VideoInterface : PVideoInterface) : boolean;
|
function enable(VideoInterface : PVideoInterface) : boolean;
|
||||||
begin
|
begin
|
||||||
tracer.push_trace('VESA.enable.enter');
|
tracer.push_trace('VESA.enable.enter');
|
||||||
initVESAFrameBuffer(@VideoInterface^.FrontBuffer, multiboot.multibootinfo^.framebuffer_addr, multiboot.multibootinfo^.framebuffer_width, multiboot.multibootinfo^.framebuffer_height, multiboot.multibootinfo^.framebuffer_bpp);
|
initVESAFrameBuffer(@VideoInterface^.FrontBuffer, multiboot.multibootinfo^.framebuffer_addr, multiboot.multibootinfo^.framebuffer_width, multiboot.multibootinfo^.framebuffer_height, multiboot.multibootinfo^.framebuffer_bpp, multiboot.multibootinfo^.framebuffer_pitch);
|
||||||
case (VideoInterface^.FrontBuffer.BitsPerPixel) of
|
case (VideoInterface^.FrontBuffer.BitsPerPixel) of
|
||||||
08:VESA8.init(@VideoInterface^.DrawRoutines);
|
08:VESA8.init(@VideoInterface^.DrawRoutines);
|
||||||
16:VESA16.init(@VideoInterface^.DrawRoutines);
|
16:VESA16.init(@VideoInterface^.DrawRoutines);
|
||||||
|
|||||||
+1
-3
@@ -123,8 +123,6 @@ begin
|
|||||||
multibootinfo:= mbinfo;
|
multibootinfo:= mbinfo;
|
||||||
multibootmagic:= mbmagic;
|
multibootmagic:= mbmagic;
|
||||||
|
|
||||||
//video.init();
|
|
||||||
|
|
||||||
{ Ensure tracer is frozen }
|
{ Ensure tracer is frozen }
|
||||||
tracer.freeze();
|
tracer.freeze();
|
||||||
|
|
||||||
@@ -181,7 +179,7 @@ begin
|
|||||||
scheduler.init();
|
scheduler.init();
|
||||||
|
|
||||||
{ Console Init }
|
{ Console Init }
|
||||||
console.init();
|
//console.init();
|
||||||
|
|
||||||
{ CPUID }
|
{ CPUID }
|
||||||
console.outputln('CPU', 'Init begin');
|
console.outputln('CPU', 'Init begin');
|
||||||
|
|||||||
Reference in new issue
Block a user