From e4621c8aaa541e048ec99d838e55adc8bd0dfbf5 Mon Sep 17 00:00:00 2001 From: Kieron Morris Date: Wed, 23 Jun 2021 02:51:56 +0100 Subject: [PATCH 01/13] Started work on refactored video. --- src/console.pas | 5 ++- src/driver/video/video.pas | 83 ++++++++++++++++++++++++++++++++++++++ src/include/color.pas | 27 +++++++++++++ src/kernel.pas | 6 ++- src/stub/stub.asm | 6 +-- 5 files changed, 121 insertions(+), 6 deletions(-) create mode 100644 src/driver/video/video.pas create mode 100644 src/include/color.pas diff --git a/src/console.pas b/src/console.pas index a52468dc..cb8cf317 100644 --- a/src/console.pas +++ b/src/console.pas @@ -1776,14 +1776,15 @@ var fb: puint32; Begin + Ready:= False; fb:= puint32(uint32(multibootinfo^.framebuffer_addr)); Console_Properties.Width:= multibootinfo^.framebuffer_width; Console_Properties.Height:= multibootinfo^.framebuffer_height; Console_Properties.BitsPerPixel:= multibootinfo^.framebuffer_bpp; Console_Properties.MAX_CELL_X:= (Console_Properties.Width div 8) - 1; Console_Properties.MAX_CELL_Y:= (Console_Properties.Height div 16) - 1; - If Console_Properties.BitsPerPixel <> 16 then while true do begin - + If Console_Properties.BitsPerPixel <> 16 then begin + exit; end; kpalloc(uint32(fb)); keyboard.hook(@keyhook); diff --git a/src/driver/video/video.pas b/src/driver/video/video.pas new file mode 100644 index 00000000..511f7646 --- /dev/null +++ b/src/driver/video/video.pas @@ -0,0 +1,83 @@ +unit video; + +interface + +uses + multiboot, lmemorymanager, tracer, color, rand; + +procedure init(); +procedure DrawPixel(X : uint32; Y : uint32; Pixel : TRGB32); + +type + TVESALinearBuffer = record + Location : uint64; + BitsPerPixel : uint8; + Width : uint32; + Height : uint32; + end; + TVESA = record + initialized : Boolean; + Framebuffer : TVESALinearBuffer; + end; + +implementation + +var + VESA : TVESA; + +procedure allocateFrameBuffer(Address : uint32; Width : uint32; Height : uint32); +var + LowerAddress, UpperAddress : uint32; + Block : uint32; + +begin + tracer.push_trace('video.allocateFrameBuffer.enter'); + LowerAddress:= ((Address) SHR 22)-1; + UpperAddress:= ((Address + (Width * Height)) SHR 22)+1; + For Block:=LowerAddress to UpperAddress do begin + kpalloc(Block SHL 22); + end; + tracer.push_trace('video.allocateFrameBuffer.enter'); +end; + +procedure init(); +var + RGB : TRGB32; + x,y : uint32; + +begin + tracer.push_trace('video.init.enter'); + If not(VESA.initialized) then begin + VESA.Framebuffer.Location:= multiboot.multibootinfo^.framebuffer_addr; + VESA.Framebuffer.BitsPerPixel:= multiboot.multibootinfo^.framebuffer_bpp; + VESA.Framebuffer.Width:= multiboot.multibootinfo^.framebuffer_width; + VESA.Framebuffer.Height:= multiboot.multibootinfo^.framebuffer_height; + allocateFrameBuffer(VESA.Framebuffer.Location, VESA.Framebuffer.Width, VESA.Framebuffer.Height); + VESA.initialized:= true; + end; + srand(98354754397); + while true do begin + Inc(RGB.R); + for x:=0 to VESA.Framebuffer.Width-1 do begin + Inc(RGB.G); + for y:=0 to VESA.Framebuffer.Height-1 do begin + DrawPixel(x,y,RGB); + Inc(RGB.B); + end; + end; + end; + tracer.push_trace('video.init.exit'); +end; + +procedure DrawPixel(X : uint32; Y : uint32; Pixel : TRGB32); +var + Location : PuInt32; + Increment : Uint32; + +begin + Location:= Puint32(VESA.Framebuffer.Location); + Increment:= (Y * VESA.Framebuffer.Width) + X; + Location[Increment]:= uint32(Pixel); +end; + +end. \ No newline at end of file diff --git a/src/include/color.pas b/src/include/color.pas new file mode 100644 index 00000000..4b81efe3 --- /dev/null +++ b/src/include/color.pas @@ -0,0 +1,27 @@ +unit color; + +interface + +type + TRGB32 = bitpacked record + B : uint8; + G : uint8; + R : uint8; + A : uint8; + end; + + TRGB16 = bitpacked record + B : UBit5; + G : UBit6; + R : UBit5; + end; + + TRGB8 = bitpacked record + B : UBit2; + G : UBit4; + R : UBit2; + end; + +implementation + +end. \ No newline at end of file diff --git a/src/kernel.pas b/src/kernel.pas index 9b40accc..45e5f67f 100644 --- a/src/kernel.pas +++ b/src/kernel.pas @@ -54,7 +54,7 @@ uses base64, rand, terminal, - hashmap, vfs; + hashmap, vfs, video; procedure kmain(mbinfo: Pmultiboot_info_t; mbmagic: uint32); stdcall; @@ -132,6 +132,8 @@ begin multibootinfo:= mbinfo; multibootmagic:= mbmagic; + //video.init(); + { Ensure tracer is frozen } tracer.freeze(); @@ -260,6 +262,8 @@ begin tracer.push_trace('kmain.TICK'); + video.init(); + while true do begin tracer.push_trace('kmain.RedrawWindows'); console.redrawWindows; diff --git a/src/stub/stub.asm b/src/stub/stub.asm index 31f879d7..2bb01079 100644 --- a/src/stub/stub.asm +++ b/src/stub/stub.asm @@ -77,9 +77,9 @@ dd 0 dd 0 dd 0 dd 0 -dd 1280 -dd 1024 -dd 16 +dd 1600 +dd 1200 +dd 32 ; ; Entrypoint From d057bfc3ff3664f3cb0e949480b2803f8e3396c5 Mon Sep 17 00:00:00 2001 From: Kieron Morris Date: Wed, 23 Jun 2021 22:19:55 +0100 Subject: [PATCH 02/13] Expaneded Video.pas and addec color.pas Backbuffer will need modification to lmemorymanager to remove the limits to allocation size. --- src/driver/video/video.pas | 96 +++++++++++++++++++++++++++++++------- src/include/color.pas | 10 ++++ src/kernel.pas | 4 +- 3 files changed, 91 insertions(+), 19 deletions(-) diff --git a/src/driver/video/video.pas b/src/driver/video/video.pas index 511f7646..0c6f3db4 100644 --- a/src/driver/video/video.pas +++ b/src/driver/video/video.pas @@ -3,29 +3,59 @@ unit video; interface uses - multiboot, lmemorymanager, tracer, color, rand; + multiboot, lmemorymanager, tracer, color, rand, console; procedure init(); procedure DrawPixel(X : uint32; Y : uint32; Pixel : TRGB32); +procedure Flush(); type + VideoBuffer = uint64; TVESALinearBuffer = record - Location : uint64; + Initialized : Boolean; + Location : VideoBuffer; + BitsPerPixel : uint8; + Width : uint32; + Height : uint32; + end; + TBackBuffer = record + Initialized : Boolean; + Location : VideoBuffer; BitsPerPixel : uint8; Width : uint32; Height : uint32; end; TVESA = record - initialized : Boolean; - Framebuffer : TVESALinearBuffer; + DefaultBuffer : VideoBuffer; + Framebuffer : TVESALinearBuffer; + BackBuffer : TBackBuffer; end; + PVESA = ^TVESA; implementation var VESA : TVESA; -procedure allocateFrameBuffer(Address : uint32; Width : uint32; Height : uint32); +function allocateBackBuffer(Width : uint32; Height : uint32; BitsPerPixel : uint8) : uint64; +begin + Outputln('VIDEO','Start Kalloc Backbuffer'); + //This doesn't currently work... Needs a rework of lmemorymanager + allocateBackBuffer:= uint64(kalloc((Width * Height) * BitsPerPixel)); + Outputln('VIDEO','End Kalloc Backbuffer'); +end; + +procedure initBackBuffer(VESAInfo : PVESA; Width : uint32; Height : uint32; BitsPerPixel : uint8); +begin + VESAInfo^.BackBuffer.Width:= Width; + VESAInfo^.BackBuffer.Height:= Height; + VESAInfo^.BackBuffer.BitsPerPixel:= BitsPerPixel; + VESAInfo^.BackBuffer.Location:= allocateBackBuffer(VESAInfo^.BackBuffer.Width, VESAInfo^.BackBuffer.Height, VESAInfo^.BackBuffer.BitsPerPixel); + VESAInfo^.DefaultBuffer:= VESAInfo^.BackBuffer.Location; + VESAInfo^.BackBuffer.Initialized:= True; +end; + +procedure allocateVESAFrameBuffer(Address : uint32; Width : uint32; Height : uint32); var LowerAddress, UpperAddress : uint32; Block : uint32; @@ -40,6 +70,19 @@ begin tracer.push_trace('video.allocateFrameBuffer.enter'); end; +procedure initVESAFrameBuffer(VESAInfo : PVESA; Location : uint64; Width : uint32; Height : uint32; BitsPerPixel : uint8); +begin + if not(VESAInfo^.Framebuffer.Initialized) then begin + VESAInfo^.Framebuffer.Location:= Location; + VESAInfo^.Framebuffer.BitsPerPixel:= BitsPerPixel; + VESAInfo^.Framebuffer.Width:= Width; + VESAInfo^.Framebuffer.Height:= Height; + allocateVESAFrameBuffer(VESAInfo^.Framebuffer.Location, VESAInfo^.Framebuffer.Width, VESAInfo^.Framebuffer.Height); + VESAInfo^.DefaultBuffer:= VESAInfo^.Framebuffer.Location; + VESAInfo^.Framebuffer.Initialized:= True; + end; +end; + procedure init(); var RGB : TRGB32; @@ -47,14 +90,12 @@ var begin tracer.push_trace('video.init.enter'); - If not(VESA.initialized) then begin - VESA.Framebuffer.Location:= multiboot.multibootinfo^.framebuffer_addr; - VESA.Framebuffer.BitsPerPixel:= multiboot.multibootinfo^.framebuffer_bpp; - VESA.Framebuffer.Width:= multiboot.multibootinfo^.framebuffer_width; - VESA.Framebuffer.Height:= multiboot.multibootinfo^.framebuffer_height; - allocateFrameBuffer(VESA.Framebuffer.Location, VESA.Framebuffer.Width, VESA.Framebuffer.Height); - VESA.initialized:= true; - end; + console.Outputln('VIDEO', 'Init VESA Framebuffer'); + initVESAFrameBuffer(@VESA, multiboot.multibootinfo^.framebuffer_addr, multiboot.multibootinfo^.framebuffer_width, multiboot.multibootinfo^.framebuffer_height, multiboot.multibootinfo^.framebuffer_bpp); + console.Outputln('VIDEO', 'Init VESA Backbuffer'); + //initBackBuffer(@VESA, multiboot.multibootinfo^.framebuffer_width, multiboot.multibootinfo^.framebuffer_height, multiboot.multibootinfo^.framebuffer_bpp); + + console.Outputln('VIDEO', 'Start Test Draw Loop'); srand(98354754397); while true do begin Inc(RGB.R); @@ -65,19 +106,40 @@ begin Inc(RGB.B); end; end; + console.Outputln('VIDEO', 'Call flush'); + Flush(); end; + tracer.push_trace('video.init.exit'); end; procedure DrawPixel(X : uint32; Y : uint32; Pixel : TRGB32); var Location : PuInt32; - Increment : Uint32; + LocationIndex : Uint32; begin - Location:= Puint32(VESA.Framebuffer.Location); - Increment:= (Y * VESA.Framebuffer.Width) + X; - Location[Increment]:= uint32(Pixel); + Location:= Puint32(VESA.DefaultBuffer); + LocationIndex:= (Y * VESA.Framebuffer.Width) + X; + Location[LocationIndex]:= uint32(Pixel); +end; + +procedure Flush(); +var + x,y : uint32; + Back,Front : PuInt32; + +begin + writestringln('Flush Start'); + if not(VESA.BackBuffer.Initialized) then exit; + Back:= PUint32(VESA.BackBuffer.Location); + Front:= PuInt32(VESA.Framebuffer.Location); + for x:=0 to VESA.Framebuffer.Width-1 do begin + for y:=0 to VESA.Framebuffer.Height-1 do begin + Front[(Y * VESA.Framebuffer.Width)+X]:= Back[(Y * VESA.Framebuffer.Width)+X]; + end; + end; + writestringln('Flush End'); end; end. \ No newline at end of file diff --git a/src/include/color.pas b/src/include/color.pas index 4b81efe3..ce5b50f6 100644 --- a/src/include/color.pas +++ b/src/include/color.pas @@ -10,6 +10,12 @@ type A : uint8; end; + TRGB24 = bitpacked record + B : uint8; + G : uint8; + R : uint8; + end; + TRGB16 = bitpacked record B : UBit5; G : UBit6; @@ -22,6 +28,10 @@ type R : UBit2; end; +const + black : TRGB32 = (B: 000; G: 000; R: 000; A: 000); + white : TRGB32 = (B: 255; G: 255; R: 255; A: 000); + implementation end. \ No newline at end of file diff --git a/src/kernel.pas b/src/kernel.pas index 45e5f67f..beada98b 100644 --- a/src/kernel.pas +++ b/src/kernel.pas @@ -200,6 +200,8 @@ begin { Call Tracer } tracer.init(); + video.init(); + { VFS Init } vfs.init(); @@ -261,8 +263,6 @@ begin rand.srand((getDateTime.Seconds SHL 24) OR (getDateTime.Minutes SHL 16) OR (getDateTime.Hours SHL 8) OR (getDateTime.Day)); tracer.push_trace('kmain.TICK'); - - video.init(); while true do begin tracer.push_trace('kmain.RedrawWindows'); From 2815dd9e4d3c4f4e6a4465947d511eb4d377cab0 Mon Sep 17 00:00:00 2001 From: Kieron Morris Date: Thu, 24 Jun 2021 01:56:53 +0100 Subject: [PATCH 03/13] Double buffering implemented Double buffering is now enabled with the use of the new large alloc (klalloc). --- src/driver/video/video.pas | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/driver/video/video.pas b/src/driver/video/video.pas index 0c6f3db4..505aac53 100644 --- a/src/driver/video/video.pas +++ b/src/driver/video/video.pas @@ -41,7 +41,7 @@ function allocateBackBuffer(Width : uint32; Height : uint32; BitsPerPixel : uint begin Outputln('VIDEO','Start Kalloc Backbuffer'); //This doesn't currently work... Needs a rework of lmemorymanager - allocateBackBuffer:= uint64(kalloc((Width * Height) * BitsPerPixel)); + allocateBackBuffer:= uint64(klalloc((Width * Height) * BitsPerPixel)); Outputln('VIDEO','End Kalloc Backbuffer'); end; @@ -93,7 +93,7 @@ begin console.Outputln('VIDEO', 'Init VESA Framebuffer'); initVESAFrameBuffer(@VESA, multiboot.multibootinfo^.framebuffer_addr, multiboot.multibootinfo^.framebuffer_width, multiboot.multibootinfo^.framebuffer_height, multiboot.multibootinfo^.framebuffer_bpp); console.Outputln('VIDEO', 'Init VESA Backbuffer'); - //initBackBuffer(@VESA, multiboot.multibootinfo^.framebuffer_width, multiboot.multibootinfo^.framebuffer_height, multiboot.multibootinfo^.framebuffer_bpp); + initBackBuffer(@VESA, multiboot.multibootinfo^.framebuffer_width, multiboot.multibootinfo^.framebuffer_height, multiboot.multibootinfo^.framebuffer_bpp); console.Outputln('VIDEO', 'Start Test Draw Loop'); srand(98354754397); @@ -106,10 +106,8 @@ begin Inc(RGB.B); end; end; - console.Outputln('VIDEO', 'Call flush'); Flush(); end; - tracer.push_trace('video.init.exit'); end; @@ -130,7 +128,6 @@ var Back,Front : PuInt32; begin - writestringln('Flush Start'); if not(VESA.BackBuffer.Initialized) then exit; Back:= PUint32(VESA.BackBuffer.Location); Front:= PuInt32(VESA.Framebuffer.Location); @@ -139,7 +136,6 @@ begin Front[(Y * VESA.Framebuffer.Width)+X]:= Back[(Y * VESA.Framebuffer.Width)+X]; end; end; - writestringln('Flush End'); end; end. \ No newline at end of file From 52b42ec9750893349540256bdabdd09a6f975a6a Mon Sep 17 00:00:00 2001 From: Kieron Morris Date: Sat, 3 Jul 2021 18:52:45 +0100 Subject: [PATCH 04/13] Enabled AVX + Changed flush to flush 2 pixels per iteration. --- src/cpu.pas | 23 +++++++++++++++++++++++ src/driver/video/video.pas | 10 +++++----- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/cpu.pas b/src/cpu.pas index 97f427a4..cc7d6db7 100644 --- a/src/cpu.pas +++ b/src/cpu.pas @@ -291,6 +291,28 @@ begin end; end; +procedure enableAVX(); +begin + if CPUID.Capabilities1^.AVX then begin + asm + PUSH EAX + PUSH ECX + PUSH EDX + XOR ECX, ECX + db $0F + db $01 + db $D0 + OR EAX, 7 + db $0F + db $01 + db $D1 + POP EDX + POP ECX + POP EAX + end; + end; +end; + procedure init(); begin terminal.registerCommand('CPU', @Terminal_Command_CPU, 'CPU Info.'); @@ -300,6 +322,7 @@ begin getCPUCapabilities; getCPUClockSpeed; enableSSE; + enableAVX; end; end. \ No newline at end of file diff --git a/src/driver/video/video.pas b/src/driver/video/video.pas index 505aac53..c53da7f6 100644 --- a/src/driver/video/video.pas +++ b/src/driver/video/video.pas @@ -125,14 +125,14 @@ end; procedure Flush(); var x,y : uint32; - Back,Front : PuInt32; + Back,Front : PuInt64; begin if not(VESA.BackBuffer.Initialized) then exit; - Back:= PUint32(VESA.BackBuffer.Location); - Front:= PuInt32(VESA.Framebuffer.Location); - for x:=0 to VESA.Framebuffer.Width-1 do begin - for y:=0 to VESA.Framebuffer.Height-1 do begin + Back:= PUint64(VESA.BackBuffer.Location); + Front:= PuInt64(VESA.Framebuffer.Location); + for x:=0 to (VESA.Framebuffer.Width-1) div 2 do begin + for y:=0 to (VESA.Framebuffer.Height-1) div 2 do begin Front[(Y * VESA.Framebuffer.Width)+X]:= Back[(Y * VESA.Framebuffer.Width)+X]; end; end; From 44f18554e1294429bcd5485bdc7aa406c0fe1e19 Mon Sep 17 00:00:00 2001 From: Kieron Morris Date: Tue, 6 Jul 2021 19:38:23 +0100 Subject: [PATCH 05/13] Abstracted video driver somewhat Split out video driver into abstract/standard/implementation. --- src/driver/video/VESA.pas | 88 ++++++++++++++++++++ src/driver/video/VESA16.pas | 41 ++++++++++ src/driver/video/VESA24.pas | 41 ++++++++++ src/driver/video/VESA32.pas | 47 +++++++++++ src/driver/video/VESA8.pas | 41 ++++++++++ src/driver/video/video.pas | 156 +++++++++++++++++------------------- 6 files changed, 330 insertions(+), 84 deletions(-) create mode 100644 src/driver/video/VESA.pas create mode 100644 src/driver/video/VESA16.pas create mode 100644 src/driver/video/VESA24.pas create mode 100644 src/driver/video/VESA32.pas create mode 100644 src/driver/video/VESA8.pas diff --git a/src/driver/video/VESA.pas b/src/driver/video/VESA.pas new file mode 100644 index 00000000..3407284b --- /dev/null +++ b/src/driver/video/VESA.pas @@ -0,0 +1,88 @@ +// Copyright 2021 Kieron Morris +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +{ + Driver->Video->VESA - Provides an interface the VESA drivers. + + @author(Kieron Morris ) +} +unit VESA; + +interface + +uses + Video, multiboot; + +procedure init(); + + +implementation + +uses + VESA8, VESA16, VESA24, VESA32; + +procedure allocateVESAFrameBuffer(Address : uint32; Width : uint32; Height : uint32); +var + LowerAddress, UpperAddress : uint32; + Block : uint32; + +begin + tracer.push_trace('vesa.allocateFrameBuffer.enter'); + LowerAddress:= ((Address) SHR 22)-1; + UpperAddress:= ((Address + (Width * Height)) SHR 22)+1; + For Block:=LowerAddress to UpperAddress do begin + kpalloc(Block SHL 22); + end; + tracer.push_trace('vesa.allocateFrameBuffer.enter'); +end; + +procedure initVESAFrameBuffer(VideoBuffer : PVideoBuffer; Location : uint64; Width : uint32; Height : uint32; BitsPerPixel : uint8); +begin + if not(VideoBuffer^.MMIOBuffer.Initialized) then begin + VideoBuffer^.MMIOBuffer.Location:= Location; + VideoBuffer^.MMIOBuffer.BitsPerPixel:= BitsPerPixel; + VideoBuffer^.MMIOBuffer.Width:= Width; + VideoBuffer^.MMIOBuffer.Height:= Height; + allocateVESAFrameBuffer(VideoBuffer^.MMIOBuffer.Location, VideoBuffer^.MMIOBuffer.Width, VideoBuffer^.MMIOBuffer.Height); + VideoBuffer^.DefaultBuffer:= VideoBuffer^.MMIOBuffer.Location; + VideoBuffer^.MMIOBuffer.Initialized:= True; + end; +end; + +procedure Flush(FrontBuffer : PVideoBuffer; BackBuffer : PVideoBuffer); +var + x,y : uint32; + Back,Front : PuInt64; + +begin + if not(BackBuffer^.Initialized) then exit; + Back:= PUint64(BackBuffer^.Location); + Front:= PuInt64(FrontBuffer^.Location); + for x:=0 to (VideoDriver.MMIOBuffer.Width-1) div 2 do begin + for y:=0 to (VideoDriver.MMIOBuffer.Height-1) div 2 do begin + Front[(Y * VideoDriver.MMIOBuffer.Width)+X]:= Back[(Y * VideoDriver.MMIOBuffer.Width)+X]; + end; + end; +end; + +procedure init(); +begin + initVESAFrameBuffer(@VideoDriver, multiboot.multibootinfo^.framebuffer_addr, multiboot.multibootinfo^.framebuffer_width, multiboot.multibootinfo^.framebuffer_height, multiboot.multibootinfo^.framebuffer_bpp); + VESA8.init(); + VESA16.init(); + VESA24.init(); + VESA32.init(); +end; + +end. \ No newline at end of file diff --git a/src/driver/video/VESA16.pas b/src/driver/video/VESA16.pas new file mode 100644 index 00000000..fe0d0116 --- /dev/null +++ b/src/driver/video/VESA16.pas @@ -0,0 +1,41 @@ +// Copyright 2021 Kieron Morris +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +{ + Driver->Video->VESA16 - Implementation of VESA 16bpp draw routines. + + @author(Kieron Morris ) +} +unit VESA16; + +interface + +uses + Video, VESA; + +procedure init(); + +implementation + +procedure DrawPixel(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); +begin + +end; + +procedure init(); +begin + +end; + +end. \ No newline at end of file diff --git a/src/driver/video/VESA24.pas b/src/driver/video/VESA24.pas new file mode 100644 index 00000000..1c6dbe70 --- /dev/null +++ b/src/driver/video/VESA24.pas @@ -0,0 +1,41 @@ +// Copyright 2021 Kieron Morris +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +{ + Driver->Video->VESA24 - Implementation of VESA 24bpp draw routines. + + @author(Kieron Morris ) +} +unit VESA24; + +interface + +uses + Video, VESA; + +procedure init(); + +implementation + +procedure DrawPixel(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); +begin + +end; + +procedure init(); +begin + +end; + +end. \ No newline at end of file diff --git a/src/driver/video/VESA32.pas b/src/driver/video/VESA32.pas new file mode 100644 index 00000000..1bfc2a10 --- /dev/null +++ b/src/driver/video/VESA32.pas @@ -0,0 +1,47 @@ +// Copyright 2021 Kieron Morris +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +{ + Driver->Video->VESA32 - Implementation of VESA 32bpp draw routines. + + @author(Kieron Morris ) +} +unit VESA32; + +interface + +uses + Video, VESA; + +procedure init(); + +implementation + +procedure DrawPixel(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); +var + Location : PuInt32; + LocationIndex : Uint32; + +begin + Location:= Puint32(Buffer^.Location); + LocationIndex:= (Y * Buffer^.Width) + X; + Location[LocationIndex]:= uint32(Pixel); +end; + +procedure init(); +begin + +end; + +end. \ No newline at end of file diff --git a/src/driver/video/VESA8.pas b/src/driver/video/VESA8.pas new file mode 100644 index 00000000..df030dc2 --- /dev/null +++ b/src/driver/video/VESA8.pas @@ -0,0 +1,41 @@ +// Copyright 2021 Kieron Morris +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +{ + Driver->Video->VESA8 - Implementation of VESA 8bpp draw routines. + + @author(Kieron Morris ) +} +unit VESA8; + +interface + +uses + Video, VESA; + +procedure init(); + +implementation + +procedure DrawPixel(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); +begin + +end; + +procedure init(); +begin + +end; + +end. \ No newline at end of file diff --git a/src/driver/video/video.pas b/src/driver/video/video.pas index c53da7f6..ea426dff 100644 --- a/src/driver/video/video.pas +++ b/src/driver/video/video.pas @@ -1,41 +1,84 @@ +// Copyright 2021 Kieron Morris +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +{ + Driver->Video->Video - Provides abstract rasterization/drawing functions. + + @author(Kieron Morris ) +} unit video; interface uses - multiboot, lmemorymanager, tracer, color, rand, console; + lmemorymanager, tracer, color, rand; procedure init(); procedure DrawPixel(X : uint32; Y : uint32; Pixel : TRGB32); procedure Flush(); type + //Arbitrary pointer to a video buffer in memory VideoBuffer = uint64; - TVESALinearBuffer = record + + //Struct representing a Memory Mapped Video Buffer + TVideoBuffer = record + //Has this buffer been initialized? Has it been paged/created in memory? Initialized : Boolean; + //Location of the video buffer in memory as a QWORD. Location : VideoBuffer; + //How many bits per pixel? BitsPerPixel : uint8; + //Width of the buffer. Width : uint32; + //Height of the buffer. Height : uint32; end; - TBackBuffer = record - Initialized : Boolean; - Location : VideoBuffer; - BitsPerPixel : uint8; - Width : uint32; - Height : uint32; + //Pointer to a video buffer + PVideoBuffer = ^TVideoBuffer; + + //Routines for drawing to the screen + TDrawRoutines = record + DrawPixel : FDrawPixel; + Flush : FFlush; end; - TVESA = record - DefaultBuffer : VideoBuffer; - Framebuffer : TVESALinearBuffer; - BackBuffer : TBackBuffer; + //Pointer to drawing routines + PDrawRoutines = ^TDrawRoutines; + + //Struct representing the whole video driver. + TVideoDriver = record + //Default buffer to be used when rendering, front buffer for no double buffering, back buffer otherwise. + DefaultBuffer : PVideoBuffer; + //Memory Mapped IO Buffer for raw rasterization. + MMIOBuffer : TVideoBuffer; + //Back buffer used for double buffering, this is flushed to MMIOBuffer with flush(); + BackBuffer : TVideoBuffer; + //Drawing Routines + DrawRoutines : TDrawRoutines; end; - PVESA = ^TVESA; + //Pointer to a video driver struct. + PVideoDriver = ^TVideoDriver; + + //Draw a pixel to screenspace + FDrawPixel = procedure(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); + //Flush backbuffer to MMIO Buffer + FFlush = procedure(FrontBuffer : PVideoBuffer; BackBuffer : PVideoBuffer); implementation var - VESA : TVESA; + VideoDriver : TVideoDriver; function allocateBackBuffer(Width : uint32; Height : uint32; BitsPerPixel : uint8) : uint64; begin @@ -45,41 +88,15 @@ begin Outputln('VIDEO','End Kalloc Backbuffer'); end; -procedure initBackBuffer(VESAInfo : PVESA; Width : uint32; Height : uint32; BitsPerPixel : uint8); +procedure initBackBuffer(DriverInfo : PVideoDriver; Width : uint32; Height : uint32; BitsPerPixel : uint8); begin - VESAInfo^.BackBuffer.Width:= Width; - VESAInfo^.BackBuffer.Height:= Height; - VESAInfo^.BackBuffer.BitsPerPixel:= BitsPerPixel; - VESAInfo^.BackBuffer.Location:= allocateBackBuffer(VESAInfo^.BackBuffer.Width, VESAInfo^.BackBuffer.Height, VESAInfo^.BackBuffer.BitsPerPixel); - VESAInfo^.DefaultBuffer:= VESAInfo^.BackBuffer.Location; - VESAInfo^.BackBuffer.Initialized:= True; -end; - -procedure allocateVESAFrameBuffer(Address : uint32; Width : uint32; Height : uint32); -var - LowerAddress, UpperAddress : uint32; - Block : uint32; - -begin - tracer.push_trace('video.allocateFrameBuffer.enter'); - LowerAddress:= ((Address) SHR 22)-1; - UpperAddress:= ((Address + (Width * Height)) SHR 22)+1; - For Block:=LowerAddress to UpperAddress do begin - kpalloc(Block SHL 22); - end; - tracer.push_trace('video.allocateFrameBuffer.enter'); -end; - -procedure initVESAFrameBuffer(VESAInfo : PVESA; Location : uint64; Width : uint32; Height : uint32; BitsPerPixel : uint8); -begin - if not(VESAInfo^.Framebuffer.Initialized) then begin - VESAInfo^.Framebuffer.Location:= Location; - VESAInfo^.Framebuffer.BitsPerPixel:= BitsPerPixel; - VESAInfo^.Framebuffer.Width:= Width; - VESAInfo^.Framebuffer.Height:= Height; - allocateVESAFrameBuffer(VESAInfo^.Framebuffer.Location, VESAInfo^.Framebuffer.Width, VESAInfo^.Framebuffer.Height); - VESAInfo^.DefaultBuffer:= VESAInfo^.Framebuffer.Location; - VESAInfo^.Framebuffer.Initialized:= True; + if not(DriverInfo^.BackBuffer.Initialized) then begin + DriverInfo^.BackBuffer.Width:= Width; + DriverInfo^.BackBuffer.Height:= Height; + DriverInfo^.BackBuffer.BitsPerPixel:= BitsPerPixel; + DriverInfo^.BackBuffer.Location:= allocateBackBuffer(DriverInfo^.BackBuffer.Width, DriverInfo^.BackBuffer.Height, DriverInfo^.BackBuffer.BitsPerPixel); + DriverInfo^.DefaultBuffer:= DriverInfo^.BackBuffer.Location; + DriverInfo^.BackBuffer.Initialized:= True; end; end; @@ -90,52 +107,23 @@ var begin tracer.push_trace('video.init.enter'); - console.Outputln('VIDEO', 'Init VESA Framebuffer'); - initVESAFrameBuffer(@VESA, multiboot.multibootinfo^.framebuffer_addr, multiboot.multibootinfo^.framebuffer_width, multiboot.multibootinfo^.framebuffer_height, multiboot.multibootinfo^.framebuffer_bpp); - console.Outputln('VIDEO', 'Init VESA Backbuffer'); - initBackBuffer(@VESA, multiboot.multibootinfo^.framebuffer_width, multiboot.multibootinfo^.framebuffer_height, multiboot.multibootinfo^.framebuffer_bpp); + + console.Outputln('VIDEO', 'Init VideoDriver MMIOBuffer'); + + console.Outputln('VIDEO', 'Init VideoDriver Backbuffer'); + //initBackBuffer(@VideoDriver, multiboot.multibootinfo^.framebuffer_width, multiboot.multibootinfo^.framebuffer_height, multiboot.multibootinfo^.framebuffer_bpp); - console.Outputln('VIDEO', 'Start Test Draw Loop'); - srand(98354754397); - while true do begin - Inc(RGB.R); - for x:=0 to VESA.Framebuffer.Width-1 do begin - Inc(RGB.G); - for y:=0 to VESA.Framebuffer.Height-1 do begin - DrawPixel(x,y,RGB); - Inc(RGB.B); - end; - end; - Flush(); - end; tracer.push_trace('video.init.exit'); end; procedure DrawPixel(X : uint32; Y : uint32; Pixel : TRGB32); -var - Location : PuInt32; - LocationIndex : Uint32; - begin - Location:= Puint32(VESA.DefaultBuffer); - LocationIndex:= (Y * VESA.Framebuffer.Width) + X; - Location[LocationIndex]:= uint32(Pixel); + end; procedure Flush(); -var - x,y : uint32; - Back,Front : PuInt64; - begin - if not(VESA.BackBuffer.Initialized) then exit; - Back:= PUint64(VESA.BackBuffer.Location); - Front:= PuInt64(VESA.Framebuffer.Location); - for x:=0 to (VESA.Framebuffer.Width-1) div 2 do begin - for y:=0 to (VESA.Framebuffer.Height-1) div 2 do begin - Front[(Y * VESA.Framebuffer.Width)+X]:= Back[(Y * VESA.Framebuffer.Width)+X]; - end; - end; + end; end. \ No newline at end of file From e7cda5811355fda5c9e4b3d9a59056231ff951d9 Mon Sep 17 00:00:00 2001 From: Kieron Morris Date: Wed, 7 Jul 2021 00:45:52 +0100 Subject: [PATCH 06/13] New modular driver set for video Started outlining how the modular driver set will look for video drawing routines. Currently supports Drawing pixels to the screen & Flushing backbuffer -> frontbuffer. Still very much test code, tracer is used everywhere for debugging, NOT DEVELOP READY. Many more draw routines need implementing - such as, but not limited to; drawRect, drawBitmap, drawLine, drawCurve, drawCircle. TODO: Implement the aforementioned routines in all VESA modes + WindowManager. --- src/driver/video/VESA.pas | 65 ++++++------ src/driver/video/VESA16.pas | 14 +-- src/driver/video/VESA24.pas | 14 +-- src/driver/video/VESA32.pas | 17 +-- src/driver/video/VESA8.pas | 14 +-- src/driver/video/doublebuffer.pas | 94 ++++++++++++++++ src/driver/video/video.pas | 171 ++++++++++++++++-------------- src/driver/video/videotypes.pas | 83 +++++++++++++++ src/include/color.pas | 22 ++++ src/kernel.pas | 26 ++++- 10 files changed, 385 insertions(+), 135 deletions(-) create mode 100644 src/driver/video/doublebuffer.pas create mode 100644 src/driver/video/videotypes.pas diff --git a/src/driver/video/VESA.pas b/src/driver/video/VESA.pas index 3407284b..ae3fcf0b 100644 --- a/src/driver/video/VESA.pas +++ b/src/driver/video/VESA.pas @@ -13,19 +13,19 @@ // limitations under the License. { - Driver->Video->VESA - Provides an interface the VESA drivers. + Driver->Video->VESA - VESA Display Driver. @author(Kieron Morris ) } -unit VESA; +unit vesa; interface uses - Video, multiboot; - -procedure init(); + videotypes, tracer, multiboot, lmemorymanager; +//Init the driver, and register with the video interface in a state ready for execution. +procedure init(Register : FRegisterDriver); implementation @@ -38,51 +38,50 @@ var Block : uint32; begin - tracer.push_trace('vesa.allocateFrameBuffer.enter'); + tracer.push_trace('VESA.allocateFrameBuffer.enter'); LowerAddress:= ((Address) SHR 22)-1; UpperAddress:= ((Address + (Width * Height)) SHR 22)+1; For Block:=LowerAddress to UpperAddress do begin kpalloc(Block SHL 22); end; - tracer.push_trace('vesa.allocateFrameBuffer.enter'); + tracer.push_trace('VESA.allocateFrameBuffer.exit'); end; procedure initVESAFrameBuffer(VideoBuffer : PVideoBuffer; Location : uint64; Width : uint32; Height : uint32; BitsPerPixel : uint8); begin - if not(VideoBuffer^.MMIOBuffer.Initialized) then begin - VideoBuffer^.MMIOBuffer.Location:= Location; - VideoBuffer^.MMIOBuffer.BitsPerPixel:= BitsPerPixel; - VideoBuffer^.MMIOBuffer.Width:= Width; - VideoBuffer^.MMIOBuffer.Height:= Height; - allocateVESAFrameBuffer(VideoBuffer^.MMIOBuffer.Location, VideoBuffer^.MMIOBuffer.Width, VideoBuffer^.MMIOBuffer.Height); - VideoBuffer^.DefaultBuffer:= VideoBuffer^.MMIOBuffer.Location; - VideoBuffer^.MMIOBuffer.Initialized:= True; + tracer.push_trace('VESA.initVESAFrameBuffer.enter'); + if not(VideoBuffer^.Initialized) then begin + VideoBuffer^.Location:= Location; + VideoBuffer^.BitsPerPixel:= BitsPerPixel; + VideoBuffer^.Width:= Width; + VideoBuffer^.Height:= Height; + allocateVESAFrameBuffer(VideoBuffer^.Location, VideoBuffer^.Width, VideoBuffer^.Height); + if VideoBuffer^.Location <> 0 then + VideoBuffer^.Initialized:= True; end; + tracer.push_trace('VESA.initVESAFrameBuffer.exit'); end; -procedure Flush(FrontBuffer : PVideoBuffer; BackBuffer : PVideoBuffer); -var - x,y : uint32; - Back,Front : PuInt64; - +function enable(VideoInterface : PVideoInterface) : boolean; begin - if not(BackBuffer^.Initialized) then exit; - Back:= PUint64(BackBuffer^.Location); - Front:= PuInt64(FrontBuffer^.Location); - for x:=0 to (VideoDriver.MMIOBuffer.Width-1) div 2 do begin - for y:=0 to (VideoDriver.MMIOBuffer.Height-1) div 2 do begin - Front[(Y * VideoDriver.MMIOBuffer.Width)+X]:= Back[(Y * VideoDriver.MMIOBuffer.Width)+X]; - end; + 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); + case (VideoInterface^.FrontBuffer.BitsPerPixel) of + 08:VESA8.init(@VideoInterface^.DrawRoutines); + 16:VESA16.init(@VideoInterface^.DrawRoutines); + 24:VESA24.init(@VideoInterface^.DrawRoutines); + 32:VESA32.init(@VideoInterface^.DrawRoutines); end; + enable:= VideoInterface^.FrontBuffer.Initialized; + tracer.push_trace('VESA.enable.exit'); end; -procedure init(); +procedure init(Register : FRegisterDriver); begin - initVESAFrameBuffer(@VideoDriver, multiboot.multibootinfo^.framebuffer_addr, multiboot.multibootinfo^.framebuffer_width, multiboot.multibootinfo^.framebuffer_height, multiboot.multibootinfo^.framebuffer_bpp); - VESA8.init(); - VESA16.init(); - VESA24.init(); - VESA32.init(); + tracer.push_trace('VESA.init.enter'); + if Register <> nil then + Register('VESA', @enable); + tracer.push_trace('VESA.init.exit'); end; end. \ No newline at end of file diff --git a/src/driver/video/VESA16.pas b/src/driver/video/VESA16.pas index fe0d0116..a15f9e0c 100644 --- a/src/driver/video/VESA16.pas +++ b/src/driver/video/VESA16.pas @@ -13,18 +13,19 @@ // limitations under the License. { - Driver->Video->VESA16 - Implementation of VESA 16bpp draw routines. + Driver->Video->VESA16 - Implementation of VESA 16bpp draw routines for the VESA Driver. @author(Kieron Morris ) } -unit VESA16; +unit vesa16; interface uses - Video, VESA; + videotypes, vesa, tracer, color; -procedure init(); +//Init the draw routines by providing what we support through the DrawRoutines struct. +procedure init(DrawRoutines : PDrawRoutines); implementation @@ -33,9 +34,10 @@ begin end; -procedure init(); +procedure init(DrawRoutines : PDrawRoutines); begin - + tracer.push_trace('vesa16.init.enter'); + tracer.push_trace('vesa16.init.exit'); end; end. \ No newline at end of file diff --git a/src/driver/video/VESA24.pas b/src/driver/video/VESA24.pas index 1c6dbe70..f4e4846b 100644 --- a/src/driver/video/VESA24.pas +++ b/src/driver/video/VESA24.pas @@ -13,18 +13,19 @@ // limitations under the License. { - Driver->Video->VESA24 - Implementation of VESA 24bpp draw routines. + Driver->Video->VESA24 - Implementation of VESA 24bpp draw routines for the VESA Driver. @author(Kieron Morris ) } -unit VESA24; +unit vesa24; interface uses - Video, VESA; + videotypes, vesa, tracer, color; -procedure init(); +//Init the draw routines by providing what we support through the DrawRoutines struct. +procedure init(DrawRoutines : PDrawRoutines); implementation @@ -33,9 +34,10 @@ begin end; -procedure init(); +procedure init(DrawRoutines : PDrawRoutines); begin - + tracer.push_trace('vesa24.init.enter'); + tracer.push_trace('vesa24.init.exit'); end; end. \ No newline at end of file diff --git a/src/driver/video/VESA32.pas b/src/driver/video/VESA32.pas index 1bfc2a10..18adf7b3 100644 --- a/src/driver/video/VESA32.pas +++ b/src/driver/video/VESA32.pas @@ -13,18 +13,19 @@ // limitations under the License. { - Driver->Video->VESA32 - Implementation of VESA 32bpp draw routines. + Driver->Video->VESA32 - Implementation of VESA 32bpp draw routines for the VESA Driver. @author(Kieron Morris ) } -unit VESA32; +unit vesa32; interface uses - Video, VESA; + videotypes, vesa, tracer, color; -procedure init(); +//Init the draw routines by providing what we support through the DrawRoutines struct. +procedure init(DrawRoutines : PDrawRoutines); implementation @@ -34,14 +35,18 @@ var LocationIndex : Uint32; begin + tracer.push_trace('vesa32.DrawPixel.enter'); Location:= Puint32(Buffer^.Location); LocationIndex:= (Y * Buffer^.Width) + X; Location[LocationIndex]:= uint32(Pixel); + tracer.push_trace('vesa32.DrawPixel.exit'); end; -procedure init(); +procedure init(DrawRoutines : PDrawRoutines); begin - + tracer.push_trace('vesa32.init.enter'); + DrawRoutines^.DrawPixel:= @DrawPixel; + tracer.push_trace('vesa32.init.exit'); end; end. \ No newline at end of file diff --git a/src/driver/video/VESA8.pas b/src/driver/video/VESA8.pas index df030dc2..e11b4e1a 100644 --- a/src/driver/video/VESA8.pas +++ b/src/driver/video/VESA8.pas @@ -13,18 +13,19 @@ // limitations under the License. { - Driver->Video->VESA8 - Implementation of VESA 8bpp draw routines. + Driver->Video->VESA8 - Implementation of VESA 8bpp draw routines for the VESA Driver. @author(Kieron Morris ) } -unit VESA8; +unit vesa8; interface uses - Video, VESA; + videotypes, vesa, tracer, color; -procedure init(); +//Init the draw routines by providing what we support through the DrawRoutines struct. +procedure init(DrawRoutines : PDrawRoutines); implementation @@ -33,9 +34,10 @@ begin end; -procedure init(); +procedure init(DrawRoutines : PDrawRoutines); begin - + tracer.push_trace('vesa8.init.enter'); + tracer.push_trace('vesa8.init.exit'); end; end. \ No newline at end of file diff --git a/src/driver/video/doublebuffer.pas b/src/driver/video/doublebuffer.pas new file mode 100644 index 00000000..2fa942bd --- /dev/null +++ b/src/driver/video/doublebuffer.pas @@ -0,0 +1,94 @@ +// Copyright 2021 Kieron Morris +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +{ + Driver->Video->Doublebuffer - Implements a very basic double buffer, tested with VESA drivers. + + @author(Kieron Morris ) +} +unit doublebuffer; + +interface + +uses + lmemorymanager, tracer, videotypes; + +//Init the driver, and register with the video interface in a state ready for execution. +procedure init(Register : FRegisterDriver); + +implementation + +function allocateBackBuffer(Width : uint32; Height : uint32; BitsPerPixel : uint8) : uint64; +begin + tracer.push_trace('doublebuffer.allocateBackBuffer.enter'); + //This doesn't currently work... Needs a rework of lmemorymanager + allocateBackBuffer:= uint64(klalloc((Width * Height) * BitsPerPixel)); + tracer.push_trace('doublebuffer.allocateBackBuffer.exit'); +end; + +procedure initBackBuffer(VInterface : PVideoInterface; Width : uint32; Height : uint32; BitsPerPixel : uint8); +begin + tracer.push_trace('doublebuffer.initBackBuffer.enter'); + if not(VInterface^.BackBuffer.Initialized) then begin + VInterface^.BackBuffer.Location:= allocateBackBuffer(Width, Height, BitsPerPixel); + if (VInterface^.BackBuffer.Location <> 0) then begin + VInterface^.BackBuffer.Width:= Width; + VInterface^.BackBuffer.Height:= Height; + VInterface^.BackBuffer.BitsPerPixel:= BitsPerPixel; + VInterface^.BackBuffer.Initialized:= True; + end; + end; + tracer.push_trace('doublebuffer.initBackBuffer.exit'); +end; + +procedure Flush(FrontBuffer : PVideoBuffer; BackBuffer : PVideoBuffer); +var + X,Y : uint32; + Back,Front : PuInt64; + +begin + tracer.push_trace('doublebuffer.Flush.enter'); + if not(BackBuffer^.Initialized) then exit; + if ((FrontBuffer^.Width > BackBuffer^.Width) or (FrontBuffer^.Height > BackBuffer^.Height)) then exit; + Back:= PUint64(BackBuffer^.Location); + Front:= PuInt64(FrontBuffer^.Location); + for X:=0 to (BackBuffer^.Width-1) div 2 do begin + for Y:=0 to (BackBuffer^.Height-1) div 2 do begin + Front[(Y * BackBuffer^.Width) + X]:= Back[(Y * BackBuffer^.Width) + X]; + end; + end; + tracer.push_trace('doublebuffer.Flush.exit'); +end; + +function enable(VideoInterface : PVideoInterface) : boolean; +begin + tracer.push_trace('doublebuffer.enable.enter'); + enable:= false; + initBackBuffer(VideoInterface, VideoInterface^.FrontBuffer.Width, VideoInterface^.FrontBuffer.Height, VideoInterface^.FrontBuffer.BitsPerPixel); + if VideoInterface^.BackBuffer.Initialized then begin + VideoInterface^.DefaultBuffer:= @VideoInterface^.BackBuffer; + VideoInterface^.DrawRoutines.Flush:= @Flush; + enable:= true; + end; + tracer.push_trace('doublebuffer.enable.exit'); +end; + +procedure init(Register : FRegisterDriver); +begin + tracer.push_trace('doublebuffer.init.enter'); + Register('BASIC_DOUBLE_BUFFER', @enable); + tracer.push_trace('doublebuffer.init.exit'); +end; + +end. \ No newline at end of file diff --git a/src/driver/video/video.pas b/src/driver/video/video.pas index ea426dff..bf23555f 100644 --- a/src/driver/video/video.pas +++ b/src/driver/video/video.pas @@ -13,7 +13,7 @@ // limitations under the License. { - Driver->Video->Video - Provides abstract rasterization/drawing functions. + Driver->Video->Video - Provides an abstract rasterization/drawing interface. @author(Kieron Morris ) } @@ -22,83 +22,37 @@ unit video; interface uses - lmemorymanager, tracer, color, rand; + lmemorymanager, tracer, color, videotypes, hashmap; procedure init(); procedure DrawPixel(X : uint32; Y : uint32; Pixel : TRGB32); procedure Flush(); - -type - //Arbitrary pointer to a video buffer in memory - VideoBuffer = uint64; - - //Struct representing a Memory Mapped Video Buffer - TVideoBuffer = record - //Has this buffer been initialized? Has it been paged/created in memory? - Initialized : Boolean; - //Location of the video buffer in memory as a QWORD. - Location : VideoBuffer; - //How many bits per pixel? - BitsPerPixel : uint8; - //Width of the buffer. - Width : uint32; - //Height of the buffer. - Height : uint32; - end; - //Pointer to a video buffer - PVideoBuffer = ^TVideoBuffer; - - //Routines for drawing to the screen - TDrawRoutines = record - DrawPixel : FDrawPixel; - Flush : FFlush; - end; - //Pointer to drawing routines - PDrawRoutines = ^TDrawRoutines; - - //Struct representing the whole video driver. - TVideoDriver = record - //Default buffer to be used when rendering, front buffer for no double buffering, back buffer otherwise. - DefaultBuffer : PVideoBuffer; - //Memory Mapped IO Buffer for raw rasterization. - MMIOBuffer : TVideoBuffer; - //Back buffer used for double buffering, this is flushed to MMIOBuffer with flush(); - BackBuffer : TVideoBuffer; - //Drawing Routines - DrawRoutines : TDrawRoutines; - end; - //Pointer to a video driver struct. - PVideoDriver = ^TVideoDriver; - - //Draw a pixel to screenspace - FDrawPixel = procedure(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); - //Flush backbuffer to MMIO Buffer - FFlush = procedure(FrontBuffer : PVideoBuffer; BackBuffer : PVideoBuffer); +function register(DriverIdentifier : pchar; EnableCallback : FEnableDriver) : boolean; +function enable(DriverIdentifier : pchar) : boolean; +function frontBufferWidth : uint32; +function frontBufferHeight : uint32; +function frontBufferBpp : uint8; +function backBufferWidth : uint32; +function backBufferHeight : uint32; +function backBufferBpp : uint8; implementation +Procedure dummyFDrawPixel(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); +begin + tracer.push_trace('video.dummyFDrawPixel.enter'); + //Do nothing +end; + +Procedure dummyFFlush(FrontBuffer : PVideoBuffer; BackBuffer : PVideoBuffer); +begin + tracer.push_trace('video.dummyFFlush.enter'); + //Do nothing +end; + var - VideoDriver : TVideoDriver; - -function allocateBackBuffer(Width : uint32; Height : uint32; BitsPerPixel : uint8) : uint64; -begin - Outputln('VIDEO','Start Kalloc Backbuffer'); - //This doesn't currently work... Needs a rework of lmemorymanager - allocateBackBuffer:= uint64(klalloc((Width * Height) * BitsPerPixel)); - Outputln('VIDEO','End Kalloc Backbuffer'); -end; - -procedure initBackBuffer(DriverInfo : PVideoDriver; Width : uint32; Height : uint32; BitsPerPixel : uint8); -begin - if not(DriverInfo^.BackBuffer.Initialized) then begin - DriverInfo^.BackBuffer.Width:= Width; - DriverInfo^.BackBuffer.Height:= Height; - DriverInfo^.BackBuffer.BitsPerPixel:= BitsPerPixel; - DriverInfo^.BackBuffer.Location:= allocateBackBuffer(DriverInfo^.BackBuffer.Width, DriverInfo^.BackBuffer.Height, DriverInfo^.BackBuffer.BitsPerPixel); - DriverInfo^.DefaultBuffer:= DriverInfo^.BackBuffer.Location; - DriverInfo^.BackBuffer.Initialized:= True; - end; -end; + VideoInterface : TVideoInterface; + DriverMap : PHashMap; procedure init(); var @@ -107,23 +61,86 @@ var begin tracer.push_trace('video.init.enter'); - - console.Outputln('VIDEO', 'Init VideoDriver MMIOBuffer'); - - console.Outputln('VIDEO', 'Init VideoDriver Backbuffer'); - //initBackBuffer(@VideoDriver, multiboot.multibootinfo^.framebuffer_width, multiboot.multibootinfo^.framebuffer_height, multiboot.multibootinfo^.framebuffer_bpp); - + VideoInterface.FrontBuffer.Initialized:= false; + VideoInterface.BackBuffer.Initialized:= false; + VideoInterface.DefaultBuffer:= @VideoInterface.FrontBuffer; + VideoInterface.DrawRoutines.DrawPixel:= @dummyFDrawPixel; + VideoInterface.DrawRoutines.Flush:= @dummyFFlush; + DriverMap:= hashmap.new; tracer.push_trace('video.init.exit'); end; +function register(DriverIdentifier : pchar; EnableCallback : FEnableDriver) : boolean; +var + Value : Void; + +begin + tracer.push_trace('video.register.enter'); + register:= false; + Value:= Hashmap.get(DriverMap, DriverIdentifier); + if (Value = nil) then begin + Hashmap.add(DriverMap, DriverIdentifier, void(EnableCallback)); + register:= true; + end; + tracer.push_trace('video.register.exit'); +end; + +function enable(DriverIdentifier : pchar) : boolean; +var + Value : Void; + +begin + tracer.push_trace('video.enable.enter'); + enable:= false; + Value:= Hashmap.get(DriverMap, DriverIdentifier); + if (Value <> nil) then begin + enable:= FEnableDriver(Value)(@VideoInterface); + end; + tracer.push_trace('video.enable.exit'); +end; + procedure DrawPixel(X : uint32; Y : uint32; Pixel : TRGB32); begin - + tracer.push_trace('video.DrawPixel.enter'); + VideoInterface.DrawRoutines.DrawPixel(VideoInterface.DefaultBuffer, X, Y, Pixel); + tracer.push_trace('video.DrawPixel.exit'); end; procedure Flush(); begin + tracer.push_trace('video.Flush.enter'); + VideoInterface.DrawRoutines.Flush(@VideoInterface.FrontBuffer, @VideoInterface.BackBuffer); + tracer.push_trace('video.Flush.exit'); +end; +function frontBufferWidth : uint32; +begin + frontBufferWidth:= VideoInterface.FrontBuffer.Width; +end; + +function frontBufferHeight : uint32; +begin + frontBufferHeight:= VideoInterface.FrontBuffer.Height; +end; + +function frontBufferBpp : uint8; +begin + frontBufferBpp:= VideoInterface.FrontBuffer.BitsPerPixel; +end; + +function backBufferWidth : uint32; +begin + backBufferWidth:= VideoInterface.BackBuffer.Width; +end; + +function backBufferHeight : uint32; +begin + backBufferHeight:= VideoInterface.BackBuffer.Height; +end; + +function backBufferBpp : uint8; +begin + backBufferBpp:= VideoInterface.BackBuffer.BitsPerPixel; end; end. \ No newline at end of file diff --git a/src/driver/video/videotypes.pas b/src/driver/video/videotypes.pas new file mode 100644 index 00000000..ee6d0d17 --- /dev/null +++ b/src/driver/video/videotypes.pas @@ -0,0 +1,83 @@ +// Copyright 2021 Kieron Morris +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +{ + Driver->Video->Videotypes - Provides types relating to the video framework & driver interface. + + @author(Kieron Morris ) +} +unit videotypes; + +interface + +uses + color; + +type + //Arbitrary pointer to a video buffer in memory + VideoBuffer = uint32; + + //Struct representing a Memory Mapped Video Buffer + TVideoBuffer = record + //Has this buffer been initialized? Has it been paged/created in memory? + Initialized : Boolean; + //Location of the video buffer in memory as a QWORD. + Location : VideoBuffer; + //How many bits per pixel? + BitsPerPixel : uint8; + //Width of the buffer. + Width : uint32; + //Height of the buffer. + Height : uint32; + end; + //Pointer to a video buffer + PVideoBuffer = ^TVideoBuffer; + + //(Abstract) Draw a pixel to screenspace + FDrawPixel = procedure(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); + //(Abstract) Flush backbuffer to MMIO Buffer + FFlush = procedure(FrontBuffer : PVideoBuffer; BackBuffer : PVideoBuffer); + + //Routines for drawing to the screen + TDrawRoutines = record + DrawPixel : FDrawPixel; + Flush : FFlush; + end; + //Pointer to drawing routines + PDrawRoutines = ^TDrawRoutines; + + //Struct representing the whole video driver. + TVideoInterface = record + //Default buffer to be used when rendering, front buffer for no double buffering, back buffer otherwise. + DefaultBuffer : PVideoBuffer; + //Memory Mapped IO Buffer for raw rasterization. + FrontBuffer : TVideoBuffer; + //Back buffer used for double buffering, this is flushed to FrontBuffer with flush(); + BackBuffer : TVideoBuffer; + //Drawing Routines + DrawRoutines : TDrawRoutines; + end; + //Pointer to a video interface struct. + PVideoInterface = ^TVideoInterface; + + //(Abstract) Enable method for a driver, called from video to enable driver. + FEnableDriver = function(VideoInterface : PVideoInterface) : boolean; + //(Abstract) Register driver, called from a driver to register with the video interface. + FRegisterDriver = function(DriverIdentifier : pchar; EnableCallback : FEnableDriver) : boolean; + //(Abstract) Init driver, called from _somewhere_ to start the driver and register it with the video interface. + FInitDriver = procedure(Register : FRegisterDriver); + +implementation + +end. \ No newline at end of file diff --git a/src/include/color.pas b/src/include/color.pas index ce5b50f6..cd22dd05 100644 --- a/src/include/color.pas +++ b/src/include/color.pas @@ -1,3 +1,22 @@ +// Copyright 2021 Kieron Morris +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +{ + Include->Color - Provides types relating to color/graphics. + + @author(Kieron Morris ) +} unit color; interface @@ -31,6 +50,9 @@ type const black : TRGB32 = (B: 000; G: 000; R: 000; A: 000); white : TRGB32 = (B: 255; G: 255; R: 255; A: 000); + red : TRGB32 = (B: 000; G: 000; R: 255; A: 000); + green : TRGB32 = (B: 000; G: 255; R: 000; A: 000); + blue : TRGB32 = (B: 255; G: 000; R: 000; A: 000); implementation diff --git a/src/kernel.pas b/src/kernel.pas index beada98b..b227878f 100644 --- a/src/kernel.pas +++ b/src/kernel.pas @@ -54,7 +54,8 @@ uses base64, rand, terminal, - hashmap, vfs, video; + hashmap, vfs, + video, vesa, doublebuffer, color; procedure kmain(mbinfo: Pmultiboot_info_t; mbmagic: uint32); stdcall; @@ -123,6 +124,8 @@ var ulf : pointer; HM : PHashMap; + + colour : TRGB32; begin { Serial Init } @@ -201,6 +204,27 @@ begin tracer.init(); video.init(); + vesa.init(@video.register); + doublebuffer.init(@video.register); + video.enable('VESA'); + video.enable('BASIC_DOUBLE_BUFFER'); + colour:= color.red; + while true do begin + for i:=0 to video.frontBufferWidth-1 do begin + for z:=0 to video.frontBufferHeight-1 do begin + video.DrawPixel(i, z, colour); + end; + end; + + if uint32(colour) = uint32(color.red) then + colour:= color.green + else if uint32(colour) = uint32(color.green) then + colour:= color.blue + else if uint32(colour) = uint32(color.blue) then + colour:= color.red; + + video.Flush(); + end; { VFS Init } vfs.init(); From 81c19bff16f0567d675241cd69bbb85b0b5bf328 Mon Sep 17 00:00:00 2001 From: Kieron Morris Date: Wed, 7 Jul 2021 17:28:06 +0100 Subject: [PATCH 07/13] Delete files to recommit with lowercase names. --- src/driver/video/VESA.pas | 87 ------------------ src/driver/video/VESA16.pas | 43 --------- src/driver/video/VESA24.pas | 43 --------- src/driver/video/VESA32.pas | 52 ----------- src/driver/video/VESA8.pas | 43 --------- src/driver/video/doublebuffer.pas | 94 ------------------- src/driver/video/video.pas | 146 ------------------------------ src/driver/video/videotypes.pas | 83 ----------------- 8 files changed, 591 deletions(-) delete mode 100644 src/driver/video/VESA.pas delete mode 100644 src/driver/video/VESA16.pas delete mode 100644 src/driver/video/VESA24.pas delete mode 100644 src/driver/video/VESA32.pas delete mode 100644 src/driver/video/VESA8.pas delete mode 100644 src/driver/video/doublebuffer.pas delete mode 100644 src/driver/video/video.pas delete mode 100644 src/driver/video/videotypes.pas diff --git a/src/driver/video/VESA.pas b/src/driver/video/VESA.pas deleted file mode 100644 index ae3fcf0b..00000000 --- a/src/driver/video/VESA.pas +++ /dev/null @@ -1,87 +0,0 @@ -// Copyright 2021 Kieron Morris -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -{ - Driver->Video->VESA - VESA Display Driver. - - @author(Kieron Morris ) -} -unit vesa; - -interface - -uses - videotypes, tracer, multiboot, lmemorymanager; - -//Init the driver, and register with the video interface in a state ready for execution. -procedure init(Register : FRegisterDriver); - -implementation - -uses - VESA8, VESA16, VESA24, VESA32; - -procedure allocateVESAFrameBuffer(Address : uint32; Width : uint32; Height : uint32); -var - LowerAddress, UpperAddress : uint32; - Block : uint32; - -begin - tracer.push_trace('VESA.allocateFrameBuffer.enter'); - LowerAddress:= ((Address) SHR 22)-1; - UpperAddress:= ((Address + (Width * Height)) SHR 22)+1; - For Block:=LowerAddress to UpperAddress do begin - kpalloc(Block SHL 22); - end; - tracer.push_trace('VESA.allocateFrameBuffer.exit'); -end; - -procedure initVESAFrameBuffer(VideoBuffer : PVideoBuffer; Location : uint64; Width : uint32; Height : uint32; BitsPerPixel : uint8); -begin - tracer.push_trace('VESA.initVESAFrameBuffer.enter'); - if not(VideoBuffer^.Initialized) then begin - VideoBuffer^.Location:= Location; - VideoBuffer^.BitsPerPixel:= BitsPerPixel; - VideoBuffer^.Width:= Width; - VideoBuffer^.Height:= Height; - allocateVESAFrameBuffer(VideoBuffer^.Location, VideoBuffer^.Width, VideoBuffer^.Height); - if VideoBuffer^.Location <> 0 then - VideoBuffer^.Initialized:= True; - end; - tracer.push_trace('VESA.initVESAFrameBuffer.exit'); -end; - -function enable(VideoInterface : PVideoInterface) : boolean; -begin - 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); - case (VideoInterface^.FrontBuffer.BitsPerPixel) of - 08:VESA8.init(@VideoInterface^.DrawRoutines); - 16:VESA16.init(@VideoInterface^.DrawRoutines); - 24:VESA24.init(@VideoInterface^.DrawRoutines); - 32:VESA32.init(@VideoInterface^.DrawRoutines); - end; - enable:= VideoInterface^.FrontBuffer.Initialized; - tracer.push_trace('VESA.enable.exit'); -end; - -procedure init(Register : FRegisterDriver); -begin - tracer.push_trace('VESA.init.enter'); - if Register <> nil then - Register('VESA', @enable); - tracer.push_trace('VESA.init.exit'); -end; - -end. \ No newline at end of file diff --git a/src/driver/video/VESA16.pas b/src/driver/video/VESA16.pas deleted file mode 100644 index a15f9e0c..00000000 --- a/src/driver/video/VESA16.pas +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2021 Kieron Morris -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -{ - Driver->Video->VESA16 - Implementation of VESA 16bpp draw routines for the VESA Driver. - - @author(Kieron Morris ) -} -unit vesa16; - -interface - -uses - videotypes, vesa, tracer, color; - -//Init the draw routines by providing what we support through the DrawRoutines struct. -procedure init(DrawRoutines : PDrawRoutines); - -implementation - -procedure DrawPixel(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); -begin - -end; - -procedure init(DrawRoutines : PDrawRoutines); -begin - tracer.push_trace('vesa16.init.enter'); - tracer.push_trace('vesa16.init.exit'); -end; - -end. \ No newline at end of file diff --git a/src/driver/video/VESA24.pas b/src/driver/video/VESA24.pas deleted file mode 100644 index f4e4846b..00000000 --- a/src/driver/video/VESA24.pas +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2021 Kieron Morris -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -{ - Driver->Video->VESA24 - Implementation of VESA 24bpp draw routines for the VESA Driver. - - @author(Kieron Morris ) -} -unit vesa24; - -interface - -uses - videotypes, vesa, tracer, color; - -//Init the draw routines by providing what we support through the DrawRoutines struct. -procedure init(DrawRoutines : PDrawRoutines); - -implementation - -procedure DrawPixel(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); -begin - -end; - -procedure init(DrawRoutines : PDrawRoutines); -begin - tracer.push_trace('vesa24.init.enter'); - tracer.push_trace('vesa24.init.exit'); -end; - -end. \ No newline at end of file diff --git a/src/driver/video/VESA32.pas b/src/driver/video/VESA32.pas deleted file mode 100644 index 18adf7b3..00000000 --- a/src/driver/video/VESA32.pas +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2021 Kieron Morris -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -{ - Driver->Video->VESA32 - Implementation of VESA 32bpp draw routines for the VESA Driver. - - @author(Kieron Morris ) -} -unit vesa32; - -interface - -uses - videotypes, vesa, tracer, color; - -//Init the draw routines by providing what we support through the DrawRoutines struct. -procedure init(DrawRoutines : PDrawRoutines); - -implementation - -procedure DrawPixel(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); -var - Location : PuInt32; - LocationIndex : Uint32; - -begin - tracer.push_trace('vesa32.DrawPixel.enter'); - Location:= Puint32(Buffer^.Location); - LocationIndex:= (Y * Buffer^.Width) + X; - Location[LocationIndex]:= uint32(Pixel); - tracer.push_trace('vesa32.DrawPixel.exit'); -end; - -procedure init(DrawRoutines : PDrawRoutines); -begin - tracer.push_trace('vesa32.init.enter'); - DrawRoutines^.DrawPixel:= @DrawPixel; - tracer.push_trace('vesa32.init.exit'); -end; - -end. \ No newline at end of file diff --git a/src/driver/video/VESA8.pas b/src/driver/video/VESA8.pas deleted file mode 100644 index e11b4e1a..00000000 --- a/src/driver/video/VESA8.pas +++ /dev/null @@ -1,43 +0,0 @@ -// Copyright 2021 Kieron Morris -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -{ - Driver->Video->VESA8 - Implementation of VESA 8bpp draw routines for the VESA Driver. - - @author(Kieron Morris ) -} -unit vesa8; - -interface - -uses - videotypes, vesa, tracer, color; - -//Init the draw routines by providing what we support through the DrawRoutines struct. -procedure init(DrawRoutines : PDrawRoutines); - -implementation - -procedure DrawPixel(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); -begin - -end; - -procedure init(DrawRoutines : PDrawRoutines); -begin - tracer.push_trace('vesa8.init.enter'); - tracer.push_trace('vesa8.init.exit'); -end; - -end. \ No newline at end of file diff --git a/src/driver/video/doublebuffer.pas b/src/driver/video/doublebuffer.pas deleted file mode 100644 index 2fa942bd..00000000 --- a/src/driver/video/doublebuffer.pas +++ /dev/null @@ -1,94 +0,0 @@ -// Copyright 2021 Kieron Morris -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -{ - Driver->Video->Doublebuffer - Implements a very basic double buffer, tested with VESA drivers. - - @author(Kieron Morris ) -} -unit doublebuffer; - -interface - -uses - lmemorymanager, tracer, videotypes; - -//Init the driver, and register with the video interface in a state ready for execution. -procedure init(Register : FRegisterDriver); - -implementation - -function allocateBackBuffer(Width : uint32; Height : uint32; BitsPerPixel : uint8) : uint64; -begin - tracer.push_trace('doublebuffer.allocateBackBuffer.enter'); - //This doesn't currently work... Needs a rework of lmemorymanager - allocateBackBuffer:= uint64(klalloc((Width * Height) * BitsPerPixel)); - tracer.push_trace('doublebuffer.allocateBackBuffer.exit'); -end; - -procedure initBackBuffer(VInterface : PVideoInterface; Width : uint32; Height : uint32; BitsPerPixel : uint8); -begin - tracer.push_trace('doublebuffer.initBackBuffer.enter'); - if not(VInterface^.BackBuffer.Initialized) then begin - VInterface^.BackBuffer.Location:= allocateBackBuffer(Width, Height, BitsPerPixel); - if (VInterface^.BackBuffer.Location <> 0) then begin - VInterface^.BackBuffer.Width:= Width; - VInterface^.BackBuffer.Height:= Height; - VInterface^.BackBuffer.BitsPerPixel:= BitsPerPixel; - VInterface^.BackBuffer.Initialized:= True; - end; - end; - tracer.push_trace('doublebuffer.initBackBuffer.exit'); -end; - -procedure Flush(FrontBuffer : PVideoBuffer; BackBuffer : PVideoBuffer); -var - X,Y : uint32; - Back,Front : PuInt64; - -begin - tracer.push_trace('doublebuffer.Flush.enter'); - if not(BackBuffer^.Initialized) then exit; - if ((FrontBuffer^.Width > BackBuffer^.Width) or (FrontBuffer^.Height > BackBuffer^.Height)) then exit; - Back:= PUint64(BackBuffer^.Location); - Front:= PuInt64(FrontBuffer^.Location); - for X:=0 to (BackBuffer^.Width-1) div 2 do begin - for Y:=0 to (BackBuffer^.Height-1) div 2 do begin - Front[(Y * BackBuffer^.Width) + X]:= Back[(Y * BackBuffer^.Width) + X]; - end; - end; - tracer.push_trace('doublebuffer.Flush.exit'); -end; - -function enable(VideoInterface : PVideoInterface) : boolean; -begin - tracer.push_trace('doublebuffer.enable.enter'); - enable:= false; - initBackBuffer(VideoInterface, VideoInterface^.FrontBuffer.Width, VideoInterface^.FrontBuffer.Height, VideoInterface^.FrontBuffer.BitsPerPixel); - if VideoInterface^.BackBuffer.Initialized then begin - VideoInterface^.DefaultBuffer:= @VideoInterface^.BackBuffer; - VideoInterface^.DrawRoutines.Flush:= @Flush; - enable:= true; - end; - tracer.push_trace('doublebuffer.enable.exit'); -end; - -procedure init(Register : FRegisterDriver); -begin - tracer.push_trace('doublebuffer.init.enter'); - Register('BASIC_DOUBLE_BUFFER', @enable); - tracer.push_trace('doublebuffer.init.exit'); -end; - -end. \ No newline at end of file diff --git a/src/driver/video/video.pas b/src/driver/video/video.pas deleted file mode 100644 index bf23555f..00000000 --- a/src/driver/video/video.pas +++ /dev/null @@ -1,146 +0,0 @@ -// Copyright 2021 Kieron Morris -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -{ - Driver->Video->Video - Provides an abstract rasterization/drawing interface. - - @author(Kieron Morris ) -} -unit video; - -interface - -uses - lmemorymanager, tracer, color, videotypes, hashmap; - -procedure init(); -procedure DrawPixel(X : uint32; Y : uint32; Pixel : TRGB32); -procedure Flush(); -function register(DriverIdentifier : pchar; EnableCallback : FEnableDriver) : boolean; -function enable(DriverIdentifier : pchar) : boolean; -function frontBufferWidth : uint32; -function frontBufferHeight : uint32; -function frontBufferBpp : uint8; -function backBufferWidth : uint32; -function backBufferHeight : uint32; -function backBufferBpp : uint8; - -implementation - -Procedure dummyFDrawPixel(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); -begin - tracer.push_trace('video.dummyFDrawPixel.enter'); - //Do nothing -end; - -Procedure dummyFFlush(FrontBuffer : PVideoBuffer; BackBuffer : PVideoBuffer); -begin - tracer.push_trace('video.dummyFFlush.enter'); - //Do nothing -end; - -var - VideoInterface : TVideoInterface; - DriverMap : PHashMap; - -procedure init(); -var - RGB : TRGB32; - x,y : uint32; - -begin - tracer.push_trace('video.init.enter'); - VideoInterface.FrontBuffer.Initialized:= false; - VideoInterface.BackBuffer.Initialized:= false; - VideoInterface.DefaultBuffer:= @VideoInterface.FrontBuffer; - VideoInterface.DrawRoutines.DrawPixel:= @dummyFDrawPixel; - VideoInterface.DrawRoutines.Flush:= @dummyFFlush; - DriverMap:= hashmap.new; - tracer.push_trace('video.init.exit'); -end; - -function register(DriverIdentifier : pchar; EnableCallback : FEnableDriver) : boolean; -var - Value : Void; - -begin - tracer.push_trace('video.register.enter'); - register:= false; - Value:= Hashmap.get(DriverMap, DriverIdentifier); - if (Value = nil) then begin - Hashmap.add(DriverMap, DriverIdentifier, void(EnableCallback)); - register:= true; - end; - tracer.push_trace('video.register.exit'); -end; - -function enable(DriverIdentifier : pchar) : boolean; -var - Value : Void; - -begin - tracer.push_trace('video.enable.enter'); - enable:= false; - Value:= Hashmap.get(DriverMap, DriverIdentifier); - if (Value <> nil) then begin - enable:= FEnableDriver(Value)(@VideoInterface); - end; - tracer.push_trace('video.enable.exit'); -end; - -procedure DrawPixel(X : uint32; Y : uint32; Pixel : TRGB32); -begin - tracer.push_trace('video.DrawPixel.enter'); - VideoInterface.DrawRoutines.DrawPixel(VideoInterface.DefaultBuffer, X, Y, Pixel); - tracer.push_trace('video.DrawPixel.exit'); -end; - -procedure Flush(); -begin - tracer.push_trace('video.Flush.enter'); - VideoInterface.DrawRoutines.Flush(@VideoInterface.FrontBuffer, @VideoInterface.BackBuffer); - tracer.push_trace('video.Flush.exit'); -end; - -function frontBufferWidth : uint32; -begin - frontBufferWidth:= VideoInterface.FrontBuffer.Width; -end; - -function frontBufferHeight : uint32; -begin - frontBufferHeight:= VideoInterface.FrontBuffer.Height; -end; - -function frontBufferBpp : uint8; -begin - frontBufferBpp:= VideoInterface.FrontBuffer.BitsPerPixel; -end; - -function backBufferWidth : uint32; -begin - backBufferWidth:= VideoInterface.BackBuffer.Width; -end; - -function backBufferHeight : uint32; -begin - backBufferHeight:= VideoInterface.BackBuffer.Height; -end; - -function backBufferBpp : uint8; -begin - backBufferBpp:= VideoInterface.BackBuffer.BitsPerPixel; -end; - -end. \ No newline at end of file diff --git a/src/driver/video/videotypes.pas b/src/driver/video/videotypes.pas deleted file mode 100644 index ee6d0d17..00000000 --- a/src/driver/video/videotypes.pas +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2021 Kieron Morris -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -{ - Driver->Video->Videotypes - Provides types relating to the video framework & driver interface. - - @author(Kieron Morris ) -} -unit videotypes; - -interface - -uses - color; - -type - //Arbitrary pointer to a video buffer in memory - VideoBuffer = uint32; - - //Struct representing a Memory Mapped Video Buffer - TVideoBuffer = record - //Has this buffer been initialized? Has it been paged/created in memory? - Initialized : Boolean; - //Location of the video buffer in memory as a QWORD. - Location : VideoBuffer; - //How many bits per pixel? - BitsPerPixel : uint8; - //Width of the buffer. - Width : uint32; - //Height of the buffer. - Height : uint32; - end; - //Pointer to a video buffer - PVideoBuffer = ^TVideoBuffer; - - //(Abstract) Draw a pixel to screenspace - FDrawPixel = procedure(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); - //(Abstract) Flush backbuffer to MMIO Buffer - FFlush = procedure(FrontBuffer : PVideoBuffer; BackBuffer : PVideoBuffer); - - //Routines for drawing to the screen - TDrawRoutines = record - DrawPixel : FDrawPixel; - Flush : FFlush; - end; - //Pointer to drawing routines - PDrawRoutines = ^TDrawRoutines; - - //Struct representing the whole video driver. - TVideoInterface = record - //Default buffer to be used when rendering, front buffer for no double buffering, back buffer otherwise. - DefaultBuffer : PVideoBuffer; - //Memory Mapped IO Buffer for raw rasterization. - FrontBuffer : TVideoBuffer; - //Back buffer used for double buffering, this is flushed to FrontBuffer with flush(); - BackBuffer : TVideoBuffer; - //Drawing Routines - DrawRoutines : TDrawRoutines; - end; - //Pointer to a video interface struct. - PVideoInterface = ^TVideoInterface; - - //(Abstract) Enable method for a driver, called from video to enable driver. - FEnableDriver = function(VideoInterface : PVideoInterface) : boolean; - //(Abstract) Register driver, called from a driver to register with the video interface. - FRegisterDriver = function(DriverIdentifier : pchar; EnableCallback : FEnableDriver) : boolean; - //(Abstract) Init driver, called from _somewhere_ to start the driver and register it with the video interface. - FInitDriver = procedure(Register : FRegisterDriver); - -implementation - -end. \ No newline at end of file From ee17f691150ef1b782250e56fe9260f1f533f0ad Mon Sep 17 00:00:00 2001 From: Kieron Morris Date: Wed, 7 Jul 2021 17:32:07 +0100 Subject: [PATCH 08/13] Fixed files being weird with case/unit searches --- src/driver/video/doublebuffer.pas | 94 +++++++++++++++++++ src/driver/video/vesa.pas | 87 ++++++++++++++++++ src/driver/video/vesa16.pas | 43 +++++++++ src/driver/video/vesa24.pas | 43 +++++++++ src/driver/video/vesa32.pas | 52 +++++++++++ src/driver/video/vesa8.pas | 43 +++++++++ src/driver/video/video.pas | 146 ++++++++++++++++++++++++++++++ src/driver/video/videotypes.pas | 83 +++++++++++++++++ 8 files changed, 591 insertions(+) create mode 100644 src/driver/video/doublebuffer.pas create mode 100644 src/driver/video/vesa.pas create mode 100644 src/driver/video/vesa16.pas create mode 100644 src/driver/video/vesa24.pas create mode 100644 src/driver/video/vesa32.pas create mode 100644 src/driver/video/vesa8.pas create mode 100644 src/driver/video/video.pas create mode 100644 src/driver/video/videotypes.pas diff --git a/src/driver/video/doublebuffer.pas b/src/driver/video/doublebuffer.pas new file mode 100644 index 00000000..2fa942bd --- /dev/null +++ b/src/driver/video/doublebuffer.pas @@ -0,0 +1,94 @@ +// Copyright 2021 Kieron Morris +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +{ + Driver->Video->Doublebuffer - Implements a very basic double buffer, tested with VESA drivers. + + @author(Kieron Morris ) +} +unit doublebuffer; + +interface + +uses + lmemorymanager, tracer, videotypes; + +//Init the driver, and register with the video interface in a state ready for execution. +procedure init(Register : FRegisterDriver); + +implementation + +function allocateBackBuffer(Width : uint32; Height : uint32; BitsPerPixel : uint8) : uint64; +begin + tracer.push_trace('doublebuffer.allocateBackBuffer.enter'); + //This doesn't currently work... Needs a rework of lmemorymanager + allocateBackBuffer:= uint64(klalloc((Width * Height) * BitsPerPixel)); + tracer.push_trace('doublebuffer.allocateBackBuffer.exit'); +end; + +procedure initBackBuffer(VInterface : PVideoInterface; Width : uint32; Height : uint32; BitsPerPixel : uint8); +begin + tracer.push_trace('doublebuffer.initBackBuffer.enter'); + if not(VInterface^.BackBuffer.Initialized) then begin + VInterface^.BackBuffer.Location:= allocateBackBuffer(Width, Height, BitsPerPixel); + if (VInterface^.BackBuffer.Location <> 0) then begin + VInterface^.BackBuffer.Width:= Width; + VInterface^.BackBuffer.Height:= Height; + VInterface^.BackBuffer.BitsPerPixel:= BitsPerPixel; + VInterface^.BackBuffer.Initialized:= True; + end; + end; + tracer.push_trace('doublebuffer.initBackBuffer.exit'); +end; + +procedure Flush(FrontBuffer : PVideoBuffer; BackBuffer : PVideoBuffer); +var + X,Y : uint32; + Back,Front : PuInt64; + +begin + tracer.push_trace('doublebuffer.Flush.enter'); + if not(BackBuffer^.Initialized) then exit; + if ((FrontBuffer^.Width > BackBuffer^.Width) or (FrontBuffer^.Height > BackBuffer^.Height)) then exit; + Back:= PUint64(BackBuffer^.Location); + Front:= PuInt64(FrontBuffer^.Location); + for X:=0 to (BackBuffer^.Width-1) div 2 do begin + for Y:=0 to (BackBuffer^.Height-1) div 2 do begin + Front[(Y * BackBuffer^.Width) + X]:= Back[(Y * BackBuffer^.Width) + X]; + end; + end; + tracer.push_trace('doublebuffer.Flush.exit'); +end; + +function enable(VideoInterface : PVideoInterface) : boolean; +begin + tracer.push_trace('doublebuffer.enable.enter'); + enable:= false; + initBackBuffer(VideoInterface, VideoInterface^.FrontBuffer.Width, VideoInterface^.FrontBuffer.Height, VideoInterface^.FrontBuffer.BitsPerPixel); + if VideoInterface^.BackBuffer.Initialized then begin + VideoInterface^.DefaultBuffer:= @VideoInterface^.BackBuffer; + VideoInterface^.DrawRoutines.Flush:= @Flush; + enable:= true; + end; + tracer.push_trace('doublebuffer.enable.exit'); +end; + +procedure init(Register : FRegisterDriver); +begin + tracer.push_trace('doublebuffer.init.enter'); + Register('BASIC_DOUBLE_BUFFER', @enable); + tracer.push_trace('doublebuffer.init.exit'); +end; + +end. \ No newline at end of file diff --git a/src/driver/video/vesa.pas b/src/driver/video/vesa.pas new file mode 100644 index 00000000..ae3fcf0b --- /dev/null +++ b/src/driver/video/vesa.pas @@ -0,0 +1,87 @@ +// Copyright 2021 Kieron Morris +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +{ + Driver->Video->VESA - VESA Display Driver. + + @author(Kieron Morris ) +} +unit vesa; + +interface + +uses + videotypes, tracer, multiboot, lmemorymanager; + +//Init the driver, and register with the video interface in a state ready for execution. +procedure init(Register : FRegisterDriver); + +implementation + +uses + VESA8, VESA16, VESA24, VESA32; + +procedure allocateVESAFrameBuffer(Address : uint32; Width : uint32; Height : uint32); +var + LowerAddress, UpperAddress : uint32; + Block : uint32; + +begin + tracer.push_trace('VESA.allocateFrameBuffer.enter'); + LowerAddress:= ((Address) SHR 22)-1; + UpperAddress:= ((Address + (Width * Height)) SHR 22)+1; + For Block:=LowerAddress to UpperAddress do begin + kpalloc(Block SHL 22); + end; + tracer.push_trace('VESA.allocateFrameBuffer.exit'); +end; + +procedure initVESAFrameBuffer(VideoBuffer : PVideoBuffer; Location : uint64; Width : uint32; Height : uint32; BitsPerPixel : uint8); +begin + tracer.push_trace('VESA.initVESAFrameBuffer.enter'); + if not(VideoBuffer^.Initialized) then begin + VideoBuffer^.Location:= Location; + VideoBuffer^.BitsPerPixel:= BitsPerPixel; + VideoBuffer^.Width:= Width; + VideoBuffer^.Height:= Height; + allocateVESAFrameBuffer(VideoBuffer^.Location, VideoBuffer^.Width, VideoBuffer^.Height); + if VideoBuffer^.Location <> 0 then + VideoBuffer^.Initialized:= True; + end; + tracer.push_trace('VESA.initVESAFrameBuffer.exit'); +end; + +function enable(VideoInterface : PVideoInterface) : boolean; +begin + 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); + case (VideoInterface^.FrontBuffer.BitsPerPixel) of + 08:VESA8.init(@VideoInterface^.DrawRoutines); + 16:VESA16.init(@VideoInterface^.DrawRoutines); + 24:VESA24.init(@VideoInterface^.DrawRoutines); + 32:VESA32.init(@VideoInterface^.DrawRoutines); + end; + enable:= VideoInterface^.FrontBuffer.Initialized; + tracer.push_trace('VESA.enable.exit'); +end; + +procedure init(Register : FRegisterDriver); +begin + tracer.push_trace('VESA.init.enter'); + if Register <> nil then + Register('VESA', @enable); + tracer.push_trace('VESA.init.exit'); +end; + +end. \ No newline at end of file diff --git a/src/driver/video/vesa16.pas b/src/driver/video/vesa16.pas new file mode 100644 index 00000000..a15f9e0c --- /dev/null +++ b/src/driver/video/vesa16.pas @@ -0,0 +1,43 @@ +// Copyright 2021 Kieron Morris +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +{ + Driver->Video->VESA16 - Implementation of VESA 16bpp draw routines for the VESA Driver. + + @author(Kieron Morris ) +} +unit vesa16; + +interface + +uses + videotypes, vesa, tracer, color; + +//Init the draw routines by providing what we support through the DrawRoutines struct. +procedure init(DrawRoutines : PDrawRoutines); + +implementation + +procedure DrawPixel(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); +begin + +end; + +procedure init(DrawRoutines : PDrawRoutines); +begin + tracer.push_trace('vesa16.init.enter'); + tracer.push_trace('vesa16.init.exit'); +end; + +end. \ No newline at end of file diff --git a/src/driver/video/vesa24.pas b/src/driver/video/vesa24.pas new file mode 100644 index 00000000..f4e4846b --- /dev/null +++ b/src/driver/video/vesa24.pas @@ -0,0 +1,43 @@ +// Copyright 2021 Kieron Morris +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +{ + Driver->Video->VESA24 - Implementation of VESA 24bpp draw routines for the VESA Driver. + + @author(Kieron Morris ) +} +unit vesa24; + +interface + +uses + videotypes, vesa, tracer, color; + +//Init the draw routines by providing what we support through the DrawRoutines struct. +procedure init(DrawRoutines : PDrawRoutines); + +implementation + +procedure DrawPixel(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); +begin + +end; + +procedure init(DrawRoutines : PDrawRoutines); +begin + tracer.push_trace('vesa24.init.enter'); + tracer.push_trace('vesa24.init.exit'); +end; + +end. \ No newline at end of file diff --git a/src/driver/video/vesa32.pas b/src/driver/video/vesa32.pas new file mode 100644 index 00000000..18adf7b3 --- /dev/null +++ b/src/driver/video/vesa32.pas @@ -0,0 +1,52 @@ +// Copyright 2021 Kieron Morris +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +{ + Driver->Video->VESA32 - Implementation of VESA 32bpp draw routines for the VESA Driver. + + @author(Kieron Morris ) +} +unit vesa32; + +interface + +uses + videotypes, vesa, tracer, color; + +//Init the draw routines by providing what we support through the DrawRoutines struct. +procedure init(DrawRoutines : PDrawRoutines); + +implementation + +procedure DrawPixel(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); +var + Location : PuInt32; + LocationIndex : Uint32; + +begin + tracer.push_trace('vesa32.DrawPixel.enter'); + Location:= Puint32(Buffer^.Location); + LocationIndex:= (Y * Buffer^.Width) + X; + Location[LocationIndex]:= uint32(Pixel); + tracer.push_trace('vesa32.DrawPixel.exit'); +end; + +procedure init(DrawRoutines : PDrawRoutines); +begin + tracer.push_trace('vesa32.init.enter'); + DrawRoutines^.DrawPixel:= @DrawPixel; + tracer.push_trace('vesa32.init.exit'); +end; + +end. \ No newline at end of file diff --git a/src/driver/video/vesa8.pas b/src/driver/video/vesa8.pas new file mode 100644 index 00000000..e11b4e1a --- /dev/null +++ b/src/driver/video/vesa8.pas @@ -0,0 +1,43 @@ +// Copyright 2021 Kieron Morris +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +{ + Driver->Video->VESA8 - Implementation of VESA 8bpp draw routines for the VESA Driver. + + @author(Kieron Morris ) +} +unit vesa8; + +interface + +uses + videotypes, vesa, tracer, color; + +//Init the draw routines by providing what we support through the DrawRoutines struct. +procedure init(DrawRoutines : PDrawRoutines); + +implementation + +procedure DrawPixel(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); +begin + +end; + +procedure init(DrawRoutines : PDrawRoutines); +begin + tracer.push_trace('vesa8.init.enter'); + tracer.push_trace('vesa8.init.exit'); +end; + +end. \ No newline at end of file diff --git a/src/driver/video/video.pas b/src/driver/video/video.pas new file mode 100644 index 00000000..bf23555f --- /dev/null +++ b/src/driver/video/video.pas @@ -0,0 +1,146 @@ +// Copyright 2021 Kieron Morris +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +{ + Driver->Video->Video - Provides an abstract rasterization/drawing interface. + + @author(Kieron Morris ) +} +unit video; + +interface + +uses + lmemorymanager, tracer, color, videotypes, hashmap; + +procedure init(); +procedure DrawPixel(X : uint32; Y : uint32; Pixel : TRGB32); +procedure Flush(); +function register(DriverIdentifier : pchar; EnableCallback : FEnableDriver) : boolean; +function enable(DriverIdentifier : pchar) : boolean; +function frontBufferWidth : uint32; +function frontBufferHeight : uint32; +function frontBufferBpp : uint8; +function backBufferWidth : uint32; +function backBufferHeight : uint32; +function backBufferBpp : uint8; + +implementation + +Procedure dummyFDrawPixel(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); +begin + tracer.push_trace('video.dummyFDrawPixel.enter'); + //Do nothing +end; + +Procedure dummyFFlush(FrontBuffer : PVideoBuffer; BackBuffer : PVideoBuffer); +begin + tracer.push_trace('video.dummyFFlush.enter'); + //Do nothing +end; + +var + VideoInterface : TVideoInterface; + DriverMap : PHashMap; + +procedure init(); +var + RGB : TRGB32; + x,y : uint32; + +begin + tracer.push_trace('video.init.enter'); + VideoInterface.FrontBuffer.Initialized:= false; + VideoInterface.BackBuffer.Initialized:= false; + VideoInterface.DefaultBuffer:= @VideoInterface.FrontBuffer; + VideoInterface.DrawRoutines.DrawPixel:= @dummyFDrawPixel; + VideoInterface.DrawRoutines.Flush:= @dummyFFlush; + DriverMap:= hashmap.new; + tracer.push_trace('video.init.exit'); +end; + +function register(DriverIdentifier : pchar; EnableCallback : FEnableDriver) : boolean; +var + Value : Void; + +begin + tracer.push_trace('video.register.enter'); + register:= false; + Value:= Hashmap.get(DriverMap, DriverIdentifier); + if (Value = nil) then begin + Hashmap.add(DriverMap, DriverIdentifier, void(EnableCallback)); + register:= true; + end; + tracer.push_trace('video.register.exit'); +end; + +function enable(DriverIdentifier : pchar) : boolean; +var + Value : Void; + +begin + tracer.push_trace('video.enable.enter'); + enable:= false; + Value:= Hashmap.get(DriverMap, DriverIdentifier); + if (Value <> nil) then begin + enable:= FEnableDriver(Value)(@VideoInterface); + end; + tracer.push_trace('video.enable.exit'); +end; + +procedure DrawPixel(X : uint32; Y : uint32; Pixel : TRGB32); +begin + tracer.push_trace('video.DrawPixel.enter'); + VideoInterface.DrawRoutines.DrawPixel(VideoInterface.DefaultBuffer, X, Y, Pixel); + tracer.push_trace('video.DrawPixel.exit'); +end; + +procedure Flush(); +begin + tracer.push_trace('video.Flush.enter'); + VideoInterface.DrawRoutines.Flush(@VideoInterface.FrontBuffer, @VideoInterface.BackBuffer); + tracer.push_trace('video.Flush.exit'); +end; + +function frontBufferWidth : uint32; +begin + frontBufferWidth:= VideoInterface.FrontBuffer.Width; +end; + +function frontBufferHeight : uint32; +begin + frontBufferHeight:= VideoInterface.FrontBuffer.Height; +end; + +function frontBufferBpp : uint8; +begin + frontBufferBpp:= VideoInterface.FrontBuffer.BitsPerPixel; +end; + +function backBufferWidth : uint32; +begin + backBufferWidth:= VideoInterface.BackBuffer.Width; +end; + +function backBufferHeight : uint32; +begin + backBufferHeight:= VideoInterface.BackBuffer.Height; +end; + +function backBufferBpp : uint8; +begin + backBufferBpp:= VideoInterface.BackBuffer.BitsPerPixel; +end; + +end. \ No newline at end of file diff --git a/src/driver/video/videotypes.pas b/src/driver/video/videotypes.pas new file mode 100644 index 00000000..ee6d0d17 --- /dev/null +++ b/src/driver/video/videotypes.pas @@ -0,0 +1,83 @@ +// Copyright 2021 Kieron Morris +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +{ + Driver->Video->Videotypes - Provides types relating to the video framework & driver interface. + + @author(Kieron Morris ) +} +unit videotypes; + +interface + +uses + color; + +type + //Arbitrary pointer to a video buffer in memory + VideoBuffer = uint32; + + //Struct representing a Memory Mapped Video Buffer + TVideoBuffer = record + //Has this buffer been initialized? Has it been paged/created in memory? + Initialized : Boolean; + //Location of the video buffer in memory as a QWORD. + Location : VideoBuffer; + //How many bits per pixel? + BitsPerPixel : uint8; + //Width of the buffer. + Width : uint32; + //Height of the buffer. + Height : uint32; + end; + //Pointer to a video buffer + PVideoBuffer = ^TVideoBuffer; + + //(Abstract) Draw a pixel to screenspace + FDrawPixel = procedure(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); + //(Abstract) Flush backbuffer to MMIO Buffer + FFlush = procedure(FrontBuffer : PVideoBuffer; BackBuffer : PVideoBuffer); + + //Routines for drawing to the screen + TDrawRoutines = record + DrawPixel : FDrawPixel; + Flush : FFlush; + end; + //Pointer to drawing routines + PDrawRoutines = ^TDrawRoutines; + + //Struct representing the whole video driver. + TVideoInterface = record + //Default buffer to be used when rendering, front buffer for no double buffering, back buffer otherwise. + DefaultBuffer : PVideoBuffer; + //Memory Mapped IO Buffer for raw rasterization. + FrontBuffer : TVideoBuffer; + //Back buffer used for double buffering, this is flushed to FrontBuffer with flush(); + BackBuffer : TVideoBuffer; + //Drawing Routines + DrawRoutines : TDrawRoutines; + end; + //Pointer to a video interface struct. + PVideoInterface = ^TVideoInterface; + + //(Abstract) Enable method for a driver, called from video to enable driver. + FEnableDriver = function(VideoInterface : PVideoInterface) : boolean; + //(Abstract) Register driver, called from a driver to register with the video interface. + FRegisterDriver = function(DriverIdentifier : pchar; EnableCallback : FEnableDriver) : boolean; + //(Abstract) Init driver, called from _somewhere_ to start the driver and register it with the video interface. + FInitDriver = procedure(Register : FRegisterDriver); + +implementation + +end. \ No newline at end of file From 6b81c4ece045f74a87bdda201f07e3376dbc7393 Mon Sep 17 00:00:00 2001 From: Kieron Morris Date: Sun, 23 Jan 2022 16:58:46 +0000 Subject: [PATCH 09/13] Vesa32 additions + util functions to support --- src/driver/video/vesa32.pas | 4 +- src/driver/video/video.pas | 174 ++++++++++++++++++++++++++++++-- src/driver/video/videotypes.pas | 11 +- src/include/util.pas | 11 ++ src/kernel.pas | 28 +++-- 5 files changed, 200 insertions(+), 28 deletions(-) diff --git a/src/driver/video/vesa32.pas b/src/driver/video/vesa32.pas index 18adf7b3..9d316baa 100644 --- a/src/driver/video/vesa32.pas +++ b/src/driver/video/vesa32.pas @@ -35,11 +35,11 @@ var LocationIndex : Uint32; begin - tracer.push_trace('vesa32.DrawPixel.enter'); + //tracer.push_trace('vesa32.DrawPixel.enter'); Location:= Puint32(Buffer^.Location); LocationIndex:= (Y * Buffer^.Width) + X; Location[LocationIndex]:= uint32(Pixel); - tracer.push_trace('vesa32.DrawPixel.exit'); + //tracer.push_trace('vesa32.DrawPixel.exit'); end; procedure init(DrawRoutines : PDrawRoutines); diff --git a/src/driver/video/video.pas b/src/driver/video/video.pas index bf23555f..62fdce87 100644 --- a/src/driver/video/video.pas +++ b/src/driver/video/video.pas @@ -22,13 +22,18 @@ unit video; interface uses - lmemorymanager, tracer, color, videotypes, hashmap; + lmemorymanager, tracer, color, videotypes, hashmap, util; procedure init(); procedure DrawPixel(X : uint32; Y : uint32; Pixel : TRGB32); +procedure DrawLine(x1,y1,x2,y2 : uint32; thickness : uint32; Color : TRGB32); +procedure DrawRect(x1,y1,x2,y2 : uint32; line_thickness : uint32; Color : TRGB32); +procedure FillRect(x1,y1,x2,y2 : uint32; line_thickness : uint32; Line_Color : TRGB32; Fill_Color : TRGB32); procedure Flush(); + function register(DriverIdentifier : pchar; EnableCallback : FEnableDriver) : boolean; function enable(DriverIdentifier : pchar) : boolean; + function frontBufferWidth : uint32; function frontBufferHeight : uint32; function frontBufferBpp : uint8; @@ -41,13 +46,125 @@ implementation Procedure dummyFDrawPixel(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); begin tracer.push_trace('video.dummyFDrawPixel.enter'); - //Do nothing + //Do nothing, this is the most basic function that must be implemented by a driver. end; -Procedure dummyFFlush(FrontBuffer : PVideoBuffer; BackBuffer : PVideoBuffer); +Procedure basicFFlush(FrontBuffer : PVideoBuffer; BackBuffer : PVideoBuffer); +var + x, y : uint32; + Back,Front : puint32; + begin - tracer.push_trace('video.dummyFFlush.enter'); - //Do nothing + tracer.push_trace('video.basicFFlush.enter'); + If not(FrontBuffer^.Initialized and BackBuffer^.Initialized) then exit; + if (BackBuffer^.Width > FrontBuffer^.Width) or (BackBuffer^.Height > FrontBuffer^.Height) then exit; + Back:= puint32(BackBuffer^.Location); + Front:= puint32(FrontBuffer^.Location); + for x:=0 to BackBuffer^.Width-1 do begin + for y:=0 to BackBuffer^.Height-1 do begin + Front[(Y * BackBuffer^.Width) + X]:= Back[(Y * BackBuffer^.Width) + X]; + end; + end; +end; + +procedure basicFDrawLine(Buffer : PVideoBuffer; x1,y1,x2,y2 : uint32; thickness : uint32; Color : TRGB32); +var + X, Y, DX, DY, DX1, DY1, PX, PY, XE, YE, I : sint32; + +begin + tracer.push_trace('video.basicFDrawLine.enter'); + + if(x1 = x2) then begin + for Y:=Y1 to Y2 do begin + DrawPixel(X1,Y,Color); + end; + end else if (y1 = y2) then begin + for X:=X1 to X2 do begin + DrawPixel(X,Y1,Color); + end; + end else begin + DX:= X2 - X1; + DY:= Y2 - Y1; + + DX1:= util.abs(DX); + DY1:= util.abs(DY); + + PX:= 2 * DY1 - DX1; + PY:= 2 * DX1 - DY1; + + if (DY1 <= DX1) then begin + if (dx >= 0) then begin + X:= X1; Y:= Y1; XE:= X2; + end else begin + X:= X2; Y:= Y2; XE:= X1; + end; + + DrawPixel(X, Y, Color); + + I:=0; + while (x < xe) do begin + X:= X + 1; + if (PX < 0) then begin + PX:= PX + 2 + DY1; + end else begin + if(((dx < 0) and (dy < 0)) OR ((dx > 0) and (dy > 0))) then begin + Y:= Y + 1; + end else begin + Y:= Y - 1; + end; + PX:= PX + 2 * (DY1 - DX1); + end; + DrawPixel(X,Y,Color); + I:= I + 1; + end; + end else begin + if (DY >= 0) then begin + X:= X1; Y:= Y1; YE:= Y2; + end else begin + X:= X2; Y:= Y2; YE:= Y1; + end; + + DrawPixel(X, Y, Color); + + I:=0; + while (Y < YE) do begin + Y:= Y + 1; + if (PY <= 0) then begin + PY:= PY + 2 * DX1; + end else begin + if (((dx < 0) and (dy < 0)) OR ((dx > 0) and (dy > 0))) then begin + X:= X + 1; + end else begin + X:= X - 1; + end; + PY:= PY + 2 * (dx1 - dy1); + end; + DrawPixel(X,Y,Color); + I:= I + 1; + end; + end; + end; +end; + +procedure basicFDrawRect(Buffer : PVideoBuffer; x1,y1,x2,y2 : uint32; line_thickness : uint32; Color : TRGB32); +begin + tracer.push_trace('video.basicFDrawRect.enter'); + DrawLine(x1,y1,x2,y1,line_thickness,Color); + DrawLine(x1,y2,x2,y2,line_thickness,Color); + DrawLine(x1,y1,x1,y2,line_thickness,Color); + DrawLine(x2,y1,x2,y2,line_thickness,Color); +end; + +procedure basicFFillRect(Buffer : PVideoBuffer; x1,y1,x2,y2 : uint32; line_thickness : uint32; Line_Color : TRGB32; Fill_Color : TRGB32); +var + Y : uint32; + +begin + tracer.push_trace('video.basicFFillRect.enter'); + for Y:=y1 to y2 do begin + DrawLine(x1,y,x2,y,line_thickness,Fill_Color); + end; + DrawRect(x1,y1,x2,y2,line_thickness,Line_Color); end; var @@ -61,12 +178,34 @@ var begin tracer.push_trace('video.init.enter'); + //Ensure the frontbuffer is empty & nil, ready for initialization by a driver. VideoInterface.FrontBuffer.Initialized:= false; + VideoInterface.FrontBuffer.Width:= 0; + VideoInterface.FrontBuffer.Height:= 0; + VideoInterface.FrontBuffer.BitsPerPixel:= 0; + VideoInterface.FrontBuffer.Location:= 0; + + //Ensure the backbuffer is empty & nil, ready for initialization by a driver. VideoInterface.BackBuffer.Initialized:= false; + VideoInterface.BackBuffer.Width:= 0; + VideoInterface.BackBuffer.Height:= 0; + VideoInterface.BackBuffer.BitsPerPixel:= 0; + VideoInterface.BackBuffer.Location:= 0; + + //Set the default buffer to be the FrontBuffer, assume no double buffering to begin with. VideoInterface.DefaultBuffer:= @VideoInterface.FrontBuffer; + + { Set the draw routines to point to dummy/empty routines. + Calls will still succeed but do nothing until a driver has registered. } VideoInterface.DrawRoutines.DrawPixel:= @dummyFDrawPixel; - VideoInterface.DrawRoutines.Flush:= @dummyFFlush; + VideoInterface.DrawRoutines.Flush:= @basicFFlush; + VideoInterface.DrawRoutines.DrawLine:= @basicFDrawLine; + VideoInterface.DrawRoutines.DrawRect:= @basicFDrawRect; + VideoInterface.DrawRoutines.FillRect:= @basicFFillRect; + + //Initialize our 'DriverMap', a hashmap of loadable display drivers. DriverMap:= hashmap.new; + tracer.push_trace('video.init.exit'); end; @@ -101,16 +240,31 @@ end; procedure DrawPixel(X : uint32; Y : uint32; Pixel : TRGB32); begin - tracer.push_trace('video.DrawPixel.enter'); + //tracer.push_trace('video.DrawPixel.enter'); VideoInterface.DrawRoutines.DrawPixel(VideoInterface.DefaultBuffer, X, Y, Pixel); - tracer.push_trace('video.DrawPixel.exit'); + //tracer.push_trace('video.DrawPixel.exit'); end; procedure Flush(); begin - tracer.push_trace('video.Flush.enter'); + //tracer.push_trace('video.Flush.enter'); VideoInterface.DrawRoutines.Flush(@VideoInterface.FrontBuffer, @VideoInterface.BackBuffer); - tracer.push_trace('video.Flush.exit'); + //tracer.push_trace('video.Flush.exit'); +end; + +procedure DrawLine(x1,y1,x2,y2 : uint32; thickness : uint32; Color : TRGB32); +begin + VideoInterface.DrawRoutines.DrawLine(VideoInterface.DefaultBuffer,x1,y1,x2,y2,thickness,Color); +end; + +procedure DrawRect(x1,y1,x2,y2 : uint32; line_thickness : uint32; Color : TRGB32); +begin + VideoInterface.DrawRoutines.DrawRect(VideoInterface.DefaultBuffer,x1,y1,x2,y2,line_thickness,color); +end; + +procedure FillRect(x1,y1,x2,y2 : uint32; line_thickness : uint32; Line_Color : TRGB32; Fill_Color : TRGB32); +begin + VideoInterface.DrawRoutines.FillRect(VideoInterface.DefaultBuffer,x1,y1,x2,y2,line_thickness,Line_Color,Fill_Color); end; function frontBufferWidth : uint32; diff --git a/src/driver/video/videotypes.pas b/src/driver/video/videotypes.pas index ee6d0d17..22bf512d 100644 --- a/src/driver/video/videotypes.pas +++ b/src/driver/video/videotypes.pas @@ -25,7 +25,7 @@ uses color; type - //Arbitrary pointer to a video buffer in memory + //Arbitrary pointer to a raw video buffer in memory VideoBuffer = uint32; //Struct representing a Memory Mapped Video Buffer @@ -48,11 +48,20 @@ type FDrawPixel = procedure(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); //(Abstract) Flush backbuffer to MMIO Buffer FFlush = procedure(FrontBuffer : PVideoBuffer; BackBuffer : PVideoBuffer); + //(Abstract) Draw a line to the screen + FDrawLine = procedure(Buffer : PVideoBuffer; x1,y1,x2,y2 : uint32; thickness : uint32; Color : TRGB32); + //(Abstract) Draw a rect to the screen + FDrawRect = procedure(Buffer : PVideoBuffer; x1,y1,x2,y2 : uint32; line_thickness : uint32; Color : TRGB32); + //(Abstract) Draw a filled rect to the screen + FFillRect = procedure(Buffer : PVideoBuffer; x1,y1,x2,y2 : uint32; line_thickness : uint32; Line_Color : TRGB32; Fill_Color : TRGB32); //Routines for drawing to the screen TDrawRoutines = record DrawPixel : FDrawPixel; Flush : FFlush; + DrawLine : FDrawLine; + DrawRect : FDrawRect; + FillRect : FFillRect; end; //Pointer to drawing routines PDrawRoutines = ^TDrawRoutines; diff --git a/src/include/util.pas b/src/include/util.pas index 9db9096e..39093f8f 100644 --- a/src/include/util.pas +++ b/src/include/util.pas @@ -80,6 +80,8 @@ function RorDWord(AValue : uint32; Dist : uint8) : uint32; function MsSinceSystemBoot : uint64; +function abs(x : sint32) : uint32; + var endptr : uint32; external name '__end'; stack : uint32; external name 'KERNEL_STACK'; @@ -89,6 +91,15 @@ implementation uses console, RTC, cpu, serial, strings, isr_types; +function abs(x : sint32) : uint32; +var + y : uint32; + +begin + y:= x SHR 31; + abs:= (x XOR y) - y; +end; + function MsSinceSystemBoot : uint64; begin MsSinceSystemBoot:= div6432(getTSC, (CPUID.ClockSpeed.Hz div 1000)); diff --git a/src/kernel.pas b/src/kernel.pas index b227878f..1a53c437 100644 --- a/src/kernel.pas +++ b/src/kernel.pas @@ -208,24 +208,22 @@ begin doublebuffer.init(@video.register); video.enable('VESA'); video.enable('BASIC_DOUBLE_BUFFER'); - colour:= color.red; - while true do begin - for i:=0 to video.frontBufferWidth-1 do begin - for z:=0 to video.frontBufferHeight-1 do begin - video.DrawPixel(i, z, colour); - end; - end; - - if uint32(colour) = uint32(color.red) then - colour:= color.green - else if uint32(colour) = uint32(color.green) then - colour:= color.blue - else if uint32(colour) = uint32(color.blue) then - colour:= color.red; + colour:= color.white; - video.Flush(); + for i:=0 to video.frontBufferWidth-1 do begin + for z:=0 to video.frontBufferHeight-1 do begin + video.DrawPixel(i, z, colour); + end; end; + video.DrawLine(50,50,100,100,1,color.black); + video.DrawRect(50,150,100,200,1,color.black); + video.FillRect(50,250,100,300,1,color.black,color.red); + video.DrawLine(50,350,100,350,1,color.black); + video.Flush(); + + while true do begin end; + { VFS Init } vfs.init(); From 161cea492089597e4172e5cc304d12265b6c7761 Mon Sep 17 00:00:00 2001 From: Kieron Morris Date: Sat, 29 Jan 2022 01:39:45 +0000 Subject: [PATCH 10/13] SSE MOVUPS/128bit Memcpy + Fixed Doublebuffer --- src/driver/video/doublebuffer.pas | 23 +++++++++++++++-------- src/driver/video/video.pas | 15 +++++++++------ src/include/util.pas | 9 +++++++++ 3 files changed, 33 insertions(+), 14 deletions(-) diff --git a/src/driver/video/doublebuffer.pas b/src/driver/video/doublebuffer.pas index 2fa942bd..dfff1206 100644 --- a/src/driver/video/doublebuffer.pas +++ b/src/driver/video/doublebuffer.pas @@ -22,7 +22,7 @@ unit doublebuffer; interface uses - lmemorymanager, tracer, videotypes; + lmemorymanager, tracer, videotypes, serial, util; //Init the driver, and register with the video interface in a state ready for execution. procedure init(Register : FRegisterDriver); @@ -54,21 +54,28 @@ end; procedure Flush(FrontBuffer : PVideoBuffer; BackBuffer : PVideoBuffer); var - X,Y : uint32; + idx : uint32; Back,Front : PuInt64; + BufferSize : uint32; + +const + COPY_WIDTH = 64; begin - tracer.push_trace('doublebuffer.Flush.enter'); + //tracer.push_trace('doublebuffer.Flush.enter'); if not(BackBuffer^.Initialized) then exit; if ((FrontBuffer^.Width > BackBuffer^.Width) or (FrontBuffer^.Height > BackBuffer^.Height)) then exit; Back:= PUint64(BackBuffer^.Location); Front:= PuInt64(FrontBuffer^.Location); - for X:=0 to (BackBuffer^.Width-1) div 2 do begin - for Y:=0 to (BackBuffer^.Height-1) div 2 do begin - Front[(Y * BackBuffer^.Width) + X]:= Back[(Y * BackBuffer^.Width) + X]; - end; + BufferSize:= ( ( BackBuffer^.Width * BackBuffer^.Height * BackBuffer^.BitsPerPixel) div COPY_WIDTH ) - 1; + for idx:=0 to BufferSize do begin + Front[idx]:= Back[idx]; + // -- TODO: Get SSE working here for 128bit copies -- + // __SSE_128_memcpy(uint32(Front), uint32(Back)); + // Front:= PUint64(uint32(Front) + 16); + // Back:= PUint64(uint32(Back) + 16); end; - tracer.push_trace('doublebuffer.Flush.exit'); + //tracer.push_trace('doublebuffer.Flush.exit'); end; function enable(VideoInterface : PVideoInterface) : boolean; diff --git a/src/driver/video/video.pas b/src/driver/video/video.pas index 62fdce87..1c9b6f46 100644 --- a/src/driver/video/video.pas +++ b/src/driver/video/video.pas @@ -51,19 +51,22 @@ end; Procedure basicFFlush(FrontBuffer : PVideoBuffer; BackBuffer : PVideoBuffer); var - x, y : uint32; + idx : uint32; Back,Front : puint32; + BufferSize : uint32; + +const + COPY_WIDTH = 32; begin - tracer.push_trace('video.basicFFlush.enter'); + //tracer.push_trace('video.basicFFlush.enter'); If not(FrontBuffer^.Initialized and BackBuffer^.Initialized) then exit; if (BackBuffer^.Width > FrontBuffer^.Width) or (BackBuffer^.Height > FrontBuffer^.Height) then exit; Back:= puint32(BackBuffer^.Location); Front:= puint32(FrontBuffer^.Location); - for x:=0 to BackBuffer^.Width-1 do begin - for y:=0 to BackBuffer^.Height-1 do begin - Front[(Y * BackBuffer^.Width) + X]:= Back[(Y * BackBuffer^.Width) + X]; - end; + BufferSize:= ( (BackBuffer^.Width * BackBuffer^.Height * BackBuffer^.BitsPerPixel ) div COPY_WIDTH ) - 1; + for idx:=0 to BufferSize do begin + Front[idx]:= Back[idx]; end; end; diff --git a/src/include/util.pas b/src/include/util.pas index 39093f8f..ac648a11 100644 --- a/src/include/util.pas +++ b/src/include/util.pas @@ -49,6 +49,7 @@ procedure io_wait; procedure memset(location : uint32; value : uint8; size : uint32); procedure memcpy(source : uint32; dest : uint32; size : uint32); +procedure __SSE_128_memcpy(source : uint32; dest : uint32); procedure printmemory(source : uint32; length : uint32; col : uint32; delim : PChar; offset_row : boolean); procedure printmemoryWND(source : uint32; length : uint32; col : uint32; delim : PChar; offset_row : boolean; WND : HWND); @@ -127,6 +128,14 @@ begin div6432:= (r0 SHL 32) OR r4; end; +procedure __SSE_128_memcpy(source : uint32; dest : uint32); assembler; +asm + MOV EAX, Source + MOV ECX, Dest + MOVUPS XMM0, [EAX] + MOVUPS [ECX], XMM0 +end; + function switchendian16(b : uint16) : uint16; begin switchendian16:= ((b AND $FF00) SHR 8) OR ((b AND $00FF) SHL 8); From b5582b1284fd2bdc14e409b9a9b66a12610848ae Mon Sep 17 00:00:00 2001 From: Kieron Morris Date: Sun, 30 Jan 2022 00:17:50 +0000 Subject: [PATCH 11/13] Double Buffer with SSE 128 copy working --- src/driver/video/doublebuffer.pas | 15 +++++++-------- src/include/util.pas | 6 +++--- src/kernel.pas | 29 +++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 11 deletions(-) diff --git a/src/driver/video/doublebuffer.pas b/src/driver/video/doublebuffer.pas index dfff1206..36f1ecd7 100644 --- a/src/driver/video/doublebuffer.pas +++ b/src/driver/video/doublebuffer.pas @@ -55,25 +55,24 @@ end; procedure Flush(FrontBuffer : PVideoBuffer; BackBuffer : PVideoBuffer); var idx : uint32; - Back,Front : PuInt64; + Back,Front : uint32; BufferSize : uint32; const - COPY_WIDTH = 64; + //COPY_WIDTH = 64; //Use this for 64bit copies + COPY_WIDTH = 128; //Use this for SSE copies begin //tracer.push_trace('doublebuffer.Flush.enter'); if not(BackBuffer^.Initialized) then exit; if ((FrontBuffer^.Width > BackBuffer^.Width) or (FrontBuffer^.Height > BackBuffer^.Height)) then exit; - Back:= PUint64(BackBuffer^.Location); - Front:= PuInt64(FrontBuffer^.Location); + Back:= BackBuffer^.Location; + Front:= FrontBuffer^.Location; BufferSize:= ( ( BackBuffer^.Width * BackBuffer^.Height * BackBuffer^.BitsPerPixel) div COPY_WIDTH ) - 1; for idx:=0 to BufferSize do begin - Front[idx]:= Back[idx]; + //Front[idx]:= Back[idx]; // -- TODO: Get SSE working here for 128bit copies -- - // __SSE_128_memcpy(uint32(Front), uint32(Back)); - // Front:= PUint64(uint32(Front) + 16); - // Back:= PUint64(uint32(Back) + 16); + __SSE_128_memcpy(Back + (idx * 16), Front + (idx * 16)); end; //tracer.push_trace('doublebuffer.Flush.exit'); end; diff --git a/src/include/util.pas b/src/include/util.pas index ac648a11..77069499 100644 --- a/src/include/util.pas +++ b/src/include/util.pas @@ -131,9 +131,9 @@ end; procedure __SSE_128_memcpy(source : uint32; dest : uint32); assembler; asm MOV EAX, Source - MOV ECX, Dest - MOVUPS XMM0, [EAX] - MOVUPS [ECX], XMM0 + MOVAPS XMM1, [EAX] + MOV EAX, Dest + MOVAPS [EAX], XMM1 end; function switchendian16(b : uint16) : uint16; diff --git a/src/kernel.pas b/src/kernel.pas index 1a53c437..85f26570 100644 --- a/src/kernel.pas +++ b/src/kernel.pas @@ -126,6 +126,9 @@ var HM : PHashMap; colour : TRGB32; + + array1 : Array[0..255] of char; + array2 : Array[0..255] of char; begin { Serial Init } @@ -210,6 +213,32 @@ begin video.enable('BASIC_DOUBLE_BUFFER'); colour:= color.white; + // serial.sendHex(uint32(@array1[8])); + // serial.sendHex(uint32(@array2[8])); + // for i:=8 to 23 do begin + // array2[i]:= '?'; + // end; + // array2[24]:= #0; + + // array1[8]:= 'H'; + // array1[9]:= 'e'; + // array1[10]:= 'l'; + // array1[11]:= 'l'; + // array1[12]:= 'o'; + // array1[13]:= 'w'; + // array1[14]:= 'o'; + // array1[15]:= 'r'; + // array1[16]:= 'l'; + // array1[17]:= 'd'; + // array1[18]:= '1'; + // array1[19]:= '2'; + // array1[20]:= '3'; + // array1[21]:= '4'; + // array1[22]:= '5'; + // array1[23]:= '!'; + // __SSE_128_memcpy(uint32(@array1[8]), uint32(@array2[8])); + // serial.sendString(pchar(@array2[8])); + for i:=0 to video.frontBufferWidth-1 do begin for z:=0 to video.frontBufferHeight-1 do begin video.DrawPixel(i, z, colour); From d182fd7f46e7569067b952752dd7efa2fef6582f Mon Sep 17 00:00:00 2001 From: Kieron Morris Date: Sun, 6 Feb 2022 13:25:04 +0000 Subject: [PATCH 12/13] TARGA & Texture Units Added TARGA and Texture units to represent & parse TARGA into and provide a standard texture format for use when drawing. --- src/include/color.pas | 4 +++ src/include/targa.pas | 67 +++++++++++++++++++++++++++++++++++++++++ src/include/texture.pas | 34 +++++++++++++++++++++ 3 files changed, 105 insertions(+) create mode 100644 src/include/targa.pas create mode 100644 src/include/texture.pas diff --git a/src/include/color.pas b/src/include/color.pas index cd22dd05..42039b2a 100644 --- a/src/include/color.pas +++ b/src/include/color.pas @@ -28,24 +28,28 @@ type R : uint8; A : uint8; end; + PRGB32 = ^TRGB32; TRGB24 = bitpacked record B : uint8; G : uint8; R : uint8; end; + PRGB23 = ^TRGB24; TRGB16 = bitpacked record B : UBit5; G : UBit6; R : UBit5; end; + PRGB16 = ^TRGB16; TRGB8 = bitpacked record B : UBit2; G : UBit4; R : UBit2; end; + PRGB8 = ^TRGB8; const black : TRGB32 = (B: 000; G: 000; R: 000; A: 000); diff --git a/src/include/targa.pas b/src/include/targa.pas new file mode 100644 index 00000000..6a2804aa --- /dev/null +++ b/src/include/targa.pas @@ -0,0 +1,67 @@ +unit targa; + +interface + +uses + lmemorymanager, texture; + +type + TTARGAColor = packed record + b, g, r, a: uint8; + end; + PTARGAColor = ^TTARGAColor; + + TTARGAHeader = packed record + Magic: uint8; + ColorMapType: uint8; + ImageType: uint8; + ColorMapOrigin: uint16; + ColorMapLength: uint16; + ColorMapDepth: uint8; + XOrigin: uint16; + YOrigin: uint16; + Width: uint16; + Height: uint16; + PixelDepth: uint8; + ImageDescriptor: uint8; + Data : PTARGAColor; + end; + PTARGAHeader = ^TTARGAHeader; + +Function Parse(buffer : puint8; len : uint32) : PTexture; + +implementation + +Function Parse(buffer : puint8; len : uint32) : PTexture; +var + header : PTARGAHeader; + i, j : uint32; + data : PTARGAColor; + tex : PTexture; + +begin + if (len < sizeof(TTARGAHeader)) then exit; + + header := PTARGAHeader(buffer); + if (header^.Magic <> $0) or (header^.ImageType <> 2) or (header^.PixelDepth <> 32) then exit; + + //Create a new texture + tex:= texture.newTexture(header^.Width, header^.Height); + tex^.Width:= header^.Width; + tex^.Height:= header^.Height; + + //Copy the data + data := PTARGAColor(header^.Data); + for i := 0 to header^.Height - 1 do begin + for j := 0 to header^.Width - 1 do begin + tex^.Pixels[i * header^.Width + j].r := data^.r; + tex^.Pixels[i * header^.Width + j].g := data^.g; + tex^.Pixels[i * header^.Width + j].b := data^.b; + tex^.Pixels[i * header^.Width + j].a := data^.a; + end; + end; + + Parse := tex; +end; + +end. \ No newline at end of file diff --git a/src/include/texture.pas b/src/include/texture.pas new file mode 100644 index 00000000..7c3957f2 --- /dev/null +++ b/src/include/texture.pas @@ -0,0 +1,34 @@ +unit texture; + +interface + +uses + lmemorymanager, color; + +type + TTexture = packed record + Width : uint32; + Height : uint32; + Size : uint32; + Pixels : PRGB32; + end; + PTexture = ^TTexture; + +Function newTexture(width, height: uint32): PTexture; + +implementation + +Function newTexture(width, height: uint32): PTexture; +var + texture: PTexture; + +begin + texture:= PTexture(kalloc(sizeof(TTexture))); + texture^.Pixels:= PRGB32(kalloc(width * height * sizeof(TRGB32))); + texture^.Width:= width; + texture^.Height:= height; + texture^.Size:= width * height; + newTexture:= texture; +end; + +end. \ No newline at end of file From a7111d3cacd16577a4a8dc34e79b1d8a9191cd6d Mon Sep 17 00:00:00 2001 From: Kieron Morris Date: Sun, 6 Feb 2022 13:26:12 +0000 Subject: [PATCH 13/13] Draw texture function added to Video driver. --- src/driver/video/video.pas | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/src/driver/video/video.pas b/src/driver/video/video.pas index 1c9b6f46..2ef4c46e 100644 --- a/src/driver/video/video.pas +++ b/src/driver/video/video.pas @@ -22,7 +22,7 @@ unit video; interface uses - lmemorymanager, tracer, color, videotypes, hashmap, util; + lmemorymanager, tracer, color, videotypes, hashmap, util, texture; procedure init(); procedure DrawPixel(X : uint32; Y : uint32; Pixel : TRGB32); @@ -41,6 +41,8 @@ function backBufferWidth : uint32; function backBufferHeight : uint32; function backBufferBpp : uint8; +Procedure basicFDrawTexture(Buffer : PVideoBuffer; X : uint32; Y : uint32; Texture : PTexture); + implementation Procedure dummyFDrawPixel(Buffer : PVideoBuffer; X : uint32; Y : uint32; Pixel : TRGB32); @@ -70,6 +72,19 @@ begin end; end; +Procedure basicFDrawTexture(Buffer : PVideoBuffer; X : uint32; Y : uint32; Texture : PTexture); +var + i, j : uint32; + +begin + //Draw texture to Buffer at x and y + for i:=0 to Texture^.Height - 1 do begin + for j:=0 to Texture^.Width - 1 do begin + DrawPixel(X + j, Y + i, Texture^.Pixels[(i * Texture^.Width) + j]); + end; + end; +end; + procedure basicFDrawLine(Buffer : PVideoBuffer; x1,y1,x2,y2 : uint32; thickness : uint32; Color : TRGB32); var X, Y, DX, DY, DX1, DY1, PX, PY, XE, YE, I : sint32;