mirror of
https://github.com/danbulant/Cosmos
synced 2026-05-19 12:30:32 +00:00
Please note that this version works only with Bochs. - To make it works was needed to renounce to all structures (a part for primitive types) so now Mode and Color are classes. - Implemented methods of Canvas DrawPoint(), DrawLine() and DrawRect() for now only color depth of 32 bit and integer coordinates are supported - Changed IoPort of Bochs / VBE to MemoryBlock and not MemoryBlock08 so I can write an 32 bit ARGB color in only an operation instead of 4, this will semplify the future work of RGB24 and RGB16 too. Changed the name to the correct one "LinearFrameBuffer". - Made VBEDriver more object oriented (used enums instead of hardcoded values, created methods and so on...) - Bugfix in the Pen class there was confusion in the setter / getter of the Color property - In VBEScreen removed the old code that is not needed anymore, added check to method arguments (that throws in case of fatal errors)
171 lines
6.5 KiB
C#
171 lines
6.5 KiB
C#
//#define COSMOSDEBUG
|
|
using Cosmos.HAL.Drivers;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
using Cosmos.System.Graphics;
|
|
|
|
namespace Cosmos.System
|
|
{
|
|
public class VBEScreen : Canvas
|
|
{
|
|
/// <summary>
|
|
/// Driver for Setting vbe modes and ploting/getting pixels
|
|
/// </summary>
|
|
private VBEDriver VBEDriver;
|
|
|
|
public VBEScreen() : base()
|
|
{
|
|
Global.mDebugger.SendInternal($"Creating new VBEScreen() with default mode {defaultGraphicMode}");
|
|
|
|
// We don't need to add a Control for defaultGraphicMode we assume it to be always a valid mode
|
|
VBEDriver = new VBEDriver((ushort)defaultGraphicMode.Columns, (ushort)defaultGraphicMode.Rows, (ushort)defaultGraphicMode.ColorDepth);
|
|
}
|
|
|
|
public VBEScreen(Mode mode) : base(mode)
|
|
{
|
|
//Global.mDebugger.SendInternal($"Creating new VBEScreen() with mode {mode}");
|
|
|
|
ThrowIfModeIsNotValid(mode);
|
|
|
|
VBEDriver = new VBEDriver((ushort)mode.Columns, (ushort)mode.Rows, (ushort)mode.ColorDepth);
|
|
}
|
|
|
|
public override Mode Mode
|
|
{
|
|
get
|
|
{
|
|
return mode;
|
|
}
|
|
|
|
set
|
|
{
|
|
mode = value;
|
|
SetMode(mode);
|
|
}
|
|
}
|
|
|
|
#region Display
|
|
/// <summary>
|
|
/// All the aviable screen modes VBE supports, I would like to query the hardware and obtain from it the list but I have
|
|
/// not yet find how to do it! For now I hardcode the most used VESA modes, VBE seems to support until HDTV resolution
|
|
/// without problems that is well... excellent :-)
|
|
/// </summary>
|
|
public override List<Mode> getAviableModes()
|
|
{
|
|
return new List<Mode>
|
|
{
|
|
new Mode(320, 240, ColorDepth.ColorDepth32),
|
|
new Mode(640, 480, ColorDepth.ColorDepth32),
|
|
new Mode(800, 600, ColorDepth.ColorDepth32),
|
|
new Mode(1024, 768, ColorDepth.ColorDepth32),
|
|
/* The so called HD-Ready resolution */
|
|
new Mode(1280, 720, ColorDepth.ColorDepth32),
|
|
new Mode(1280, 1024, ColorDepth.ColorDepth32),
|
|
/* A lot of HD-Ready screen uses this instead of 1280x720 */
|
|
new Mode(1366, 768, ColorDepth.ColorDepth32),
|
|
new Mode(1680, 1050, ColorDepth.ColorDepth32),
|
|
/* HDTV resolution */
|
|
new Mode(1920, 1080, ColorDepth.ColorDepth32),
|
|
/* HDTV resolution (16:10 AR) */
|
|
new Mode(1920, 1200, ColorDepth.ColorDepth32),
|
|
};
|
|
}
|
|
|
|
protected override Mode getDefaultGraphicMode() => new Mode(1024, 768, ColorDepth.ColorDepth32);
|
|
|
|
/// <summary>
|
|
/// Use this to setup the screen, this will disable the console.
|
|
/// </summary>
|
|
/// <param name="Mode">The desired Mode resolution</param>
|
|
private void SetMode(Mode mode)
|
|
{
|
|
ThrowIfModeIsNotValid(mode);
|
|
|
|
|
|
ushort xres = (ushort)Mode.Columns;
|
|
ushort yres = (ushort)Mode.Rows;
|
|
ushort bpp = (ushort)Mode.ColorDepth;
|
|
|
|
//set the screen
|
|
VBEDriver.VBESet(xres, yres, bpp);
|
|
}
|
|
#endregion
|
|
|
|
#region Drawing
|
|
|
|
public override void Clear(Color color)
|
|
{
|
|
Global.mDebugger.SendInternal($"Clearing the Screen with Color {color}");
|
|
//if (color == null)
|
|
// throw new ArgumentNullException(nameof(color));
|
|
|
|
/*
|
|
* TODO this version of Clear() works only when mode.ColorDepth == ColorDepth.ColorDepth32
|
|
* in the other cases you should before convert color and then call the opportune ClearVRAM() overload
|
|
* (the one that takes ushort for ColorDepth.ColorDepth16 and the one that takes byte for ColorDepth.ColorDepth8)
|
|
* For ColorDepth.ColorDepth24 you should mask the Alpha byte.
|
|
*/
|
|
VBEDriver.ClearVRAM((uint)color.ToArgb());
|
|
}
|
|
|
|
/*
|
|
* As DrawPoint() is the basic block of DrawLine() and DrawRect() and in theory of all the future other methods that will
|
|
* be implemented is better to not check the validity of the arguments here or it will repeat the check for any point
|
|
* to be drawn slowing down all.
|
|
*/
|
|
public override void DrawPoint(Pen pen, int x, int y)
|
|
{
|
|
Color color = pen.Color;
|
|
uint pitch;
|
|
uint stride;
|
|
uint offset;
|
|
uint ColorDepthInBytes = (uint)mode.ColorDepth / 8;
|
|
|
|
/*
|
|
* For now we can Draw only if the ColorDepth is 32 bit, we will throw otherwise.
|
|
*
|
|
* How to support other ColorDepth? The offset calculation should be the same (and so could be done out of the switch)
|
|
* adding support ColorDepth.ColorDepth24 is easier as you need can use the version of SetVRAM() that take a byte
|
|
* and call it 3 time for the B, G and R component (the Color class has properties to do this!), the problem is
|
|
* for ColorDepth.ColorDepth16 and ColorDepth.ColorDepth8 than need a conversion from color (an ARGB32 color) to the RGB16 and RGB8
|
|
* how to do this conversion faster maybe using pre-computed tables? What happens if the color cannot be converted? We will throw?
|
|
*/
|
|
switch (mode.ColorDepth)
|
|
{
|
|
case ColorDepth.ColorDepth32:
|
|
Global.mDebugger.SendInternal("Computing offset...");
|
|
pitch = (uint)mode.Columns * ColorDepthInBytes;
|
|
stride = ColorDepthInBytes;
|
|
//offset = ((uint)x * pitch) + ((uint)y * stride);
|
|
offset = ((uint)x * stride) + ((uint)y * pitch);
|
|
|
|
Global.mDebugger.SendInternal($"Drawing Point of color {color} at offset {offset}");
|
|
|
|
VBEDriver.SetVRAM(offset, (uint)color.ToArgb());
|
|
|
|
Global.mDebugger.SendInternal("Point drawn");
|
|
break;
|
|
|
|
default:
|
|
String errorMsg = "DrawPoint() with ColorDepth " + (int)Mode.ColorDepth + " not yet supported";
|
|
throw new NotImplementedException(errorMsg);
|
|
|
|
}
|
|
}
|
|
|
|
public override void DrawPoint(Pen pen, float x, float y)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
#endregion
|
|
|
|
#region Reading
|
|
// TODO add to Canvas GetPointColor()
|
|
|
|
#endregion
|
|
|
|
}
|
|
}
|