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