141 lines
4.5 KiB
ObjectPascal
141 lines
4.5 KiB
ObjectPascal
unit video;
|
|
|
|
interface
|
|
|
|
uses
|
|
multiboot, lmemorymanager, tracer, color, rand, console;
|
|
|
|
procedure init();
|
|
procedure DrawPixel(X : uint32; Y : uint32; Pixel : TRGB32);
|
|
procedure Flush();
|
|
|
|
type
|
|
VideoBuffer = uint64;
|
|
TVESALinearBuffer = record
|
|
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
|
|
DefaultBuffer : VideoBuffer;
|
|
Framebuffer : TVESALinearBuffer;
|
|
BackBuffer : TBackBuffer;
|
|
end;
|
|
PVESA = ^TVESA;
|
|
|
|
implementation
|
|
|
|
var
|
|
VESA : TVESA;
|
|
|
|
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(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;
|
|
|
|
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;
|
|
|
|
procedure init();
|
|
var
|
|
RGB : TRGB32;
|
|
x,y : uint32;
|
|
|
|
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', '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. |