Abstracted video driver somewhat

Split out video driver into abstract/standard/implementation.
This commit is contained in:
Kieron Morris 2021-07-06 19:38:23 +01:00
parent cd925e96c2
commit 78c060c114
6 changed files with 330 additions and 84 deletions

88
src/driver/video/VESA.pas Normal file
View File

@ -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 <kjm@kieronmorris.me>)
}
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.

View File

@ -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 <kjm@kieronmorris.me>)
}
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.

View File

@ -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 <kjm@kieronmorris.me>)
}
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.

View File

@ -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 <kjm@kieronmorris.me>)
}
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.

View File

@ -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 <kjm@kieronmorris.me>)
}
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.

View File

@ -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 <kjm@kieronmorris.me>)
}
unit video; unit video;
interface interface
uses uses
multiboot, lmemorymanager, tracer, color, rand, console; lmemorymanager, tracer, color, rand;
procedure init(); procedure init();
procedure DrawPixel(X : uint32; Y : uint32; Pixel : TRGB32); procedure DrawPixel(X : uint32; Y : uint32; Pixel : TRGB32);
procedure Flush(); procedure Flush();
type type
//Arbitrary pointer to a video buffer in memory
VideoBuffer = uint64; 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; Initialized : Boolean;
//Location of the video buffer in memory as a QWORD.
Location : VideoBuffer; Location : VideoBuffer;
//How many bits per pixel?
BitsPerPixel : uint8; BitsPerPixel : uint8;
//Width of the buffer.
Width : uint32; Width : uint32;
//Height of the buffer.
Height : uint32; Height : uint32;
end; end;
TBackBuffer = record //Pointer to a video buffer
Initialized : Boolean; PVideoBuffer = ^TVideoBuffer;
Location : VideoBuffer;
BitsPerPixel : uint8; //Routines for drawing to the screen
Width : uint32; TDrawRoutines = record
Height : uint32; DrawPixel : FDrawPixel;
Flush : FFlush;
end; end;
TVESA = record //Pointer to drawing routines
DefaultBuffer : VideoBuffer; PDrawRoutines = ^TDrawRoutines;
Framebuffer : TVESALinearBuffer;
BackBuffer : TBackBuffer; //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; 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 implementation
var var
VESA : TVESA; VideoDriver : TVideoDriver;
function allocateBackBuffer(Width : uint32; Height : uint32; BitsPerPixel : uint8) : uint64; function allocateBackBuffer(Width : uint32; Height : uint32; BitsPerPixel : uint8) : uint64;
begin begin
@ -45,41 +88,15 @@ begin
Outputln('VIDEO','End Kalloc Backbuffer'); Outputln('VIDEO','End Kalloc Backbuffer');
end; end;
procedure initBackBuffer(VESAInfo : PVESA; Width : uint32; Height : uint32; BitsPerPixel : uint8); procedure initBackBuffer(DriverInfo : PVideoDriver; Width : uint32; Height : uint32; BitsPerPixel : uint8);
begin begin
VESAInfo^.BackBuffer.Width:= Width; if not(DriverInfo^.BackBuffer.Initialized) then begin
VESAInfo^.BackBuffer.Height:= Height; DriverInfo^.BackBuffer.Width:= Width;
VESAInfo^.BackBuffer.BitsPerPixel:= BitsPerPixel; DriverInfo^.BackBuffer.Height:= Height;
VESAInfo^.BackBuffer.Location:= allocateBackBuffer(VESAInfo^.BackBuffer.Width, VESAInfo^.BackBuffer.Height, VESAInfo^.BackBuffer.BitsPerPixel); DriverInfo^.BackBuffer.BitsPerPixel:= BitsPerPixel;
VESAInfo^.DefaultBuffer:= VESAInfo^.BackBuffer.Location; DriverInfo^.BackBuffer.Location:= allocateBackBuffer(DriverInfo^.BackBuffer.Width, DriverInfo^.BackBuffer.Height, DriverInfo^.BackBuffer.BitsPerPixel);
VESAInfo^.BackBuffer.Initialized:= True; DriverInfo^.DefaultBuffer:= DriverInfo^.BackBuffer.Location;
end; DriverInfo^.BackBuffer.Initialized:= True;
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;
end; end;
end; end;
@ -90,52 +107,23 @@ var
begin begin
tracer.push_trace('video.init.enter'); 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', 'Start Test Draw Loop'); console.Outputln('VIDEO', 'Init VideoDriver MMIOBuffer');
srand(98354754397);
while true do begin console.Outputln('VIDEO', 'Init VideoDriver Backbuffer');
Inc(RGB.R); //initBackBuffer(@VideoDriver, multiboot.multibootinfo^.framebuffer_width, multiboot.multibootinfo^.framebuffer_height, multiboot.multibootinfo^.framebuffer_bpp);
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'); tracer.push_trace('video.init.exit');
end; end;
procedure DrawPixel(X : uint32; Y : uint32; Pixel : TRGB32); procedure DrawPixel(X : uint32; Y : uint32; Pixel : TRGB32);
var
Location : PuInt32;
LocationIndex : Uint32;
begin begin
Location:= Puint32(VESA.DefaultBuffer);
LocationIndex:= (Y * VESA.Framebuffer.Width) + X;
Location[LocationIndex]:= uint32(Pixel);
end; end;
procedure Flush(); procedure Flush();
var
x,y : uint32;
Back,Front : PuInt64;
begin 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;
end. end.