diff --git a/Demos/CosmosGraphicSubsystem/Kernel.cs b/Demos/CosmosGraphicSubsystem/Kernel.cs index 84cfe3082..8d7759f64 100644 --- a/Demos/CosmosGraphicSubsystem/Kernel.cs +++ b/Demos/CosmosGraphicSubsystem/Kernel.cs @@ -14,8 +14,8 @@ namespace Cosmos_Graphic_Subsytem protected override void BeforeRun() { Console.WriteLine("Cosmos booted successfully. Let's go in Graphic Mode"); - - /* Get on istance of the Canvas that is all the Screen */ + + /* Get on instance of the Canvas that is all the Screen */ canvas = FullScreenCanvas.GetFullScreenCanvas(); /* Clear the Screen with the color 'Blue' */ diff --git a/source/Cosmos.System2/Graphics/Canvas.cs b/source/Cosmos.System2/Graphics/Canvas.cs index dd8a2aab9..4163d4bec 100644 --- a/source/Cosmos.System2/Graphics/Canvas.cs +++ b/source/Cosmos.System2/Graphics/Canvas.cs @@ -1,4 +1,4 @@ -//#define COSMOSDEBUG +//#define COSMOSDEBUG using System; using System.Drawing; using System.Collections.Generic; @@ -93,6 +93,8 @@ namespace Cosmos.System.Graphics public abstract void DrawPoint(Pen pen, int x, int y); public abstract void DrawPoint(Pen pen, float x, float y); + + public abstract Color GetPointColor(int x, int y); public virtual void DrawArray(Color[] colors, Point point, int width, int height) { diff --git a/source/Cosmos.System2/Graphics/FullScreenCanvas.cs b/source/Cosmos.System2/Graphics/FullScreenCanvas.cs index dd7618be9..7df1c025f 100644 --- a/source/Cosmos.System2/Graphics/FullScreenCanvas.cs +++ b/source/Cosmos.System2/Graphics/FullScreenCanvas.cs @@ -1,22 +1,37 @@ -//#define COSMOSDEBUG +//#define COSMOSDEBUG using Cosmos.System.Graphics; +using Cosmos.HAL; namespace Cosmos.System.Graphics { public static class FullScreenCanvas { - /* - * For now we hardcode that the VideoDriver is always VBE when we have more that a driver supported we need to find - * what to use when we do the 'new' (inside GetFullScreenCanvas() static methods). MyVideoDriver should be - * of type Canvas - */ - static private Canvas MyVideoDriver = null; + private enum VideoDriver + { + VMWareSVGAIIDriver, + //VGADriver, + VBEDriver + } + + private static PCIDevice SVGAIIDevice = PCI.GetDevice(0x15AD, 0x0405); + + private static bool SVGAIIExists = SVGAIIDevice.DeviceExists; + + private static VideoDriver videoDevice; + + private static Canvas MyVideoDriver; public static Canvas GetFullScreenCanvas(Mode mode) { Global.mDebugger.SendInternal("GetFullScreenCanvas() with mode " + mode); - if (MyVideoDriver == null) + /* Use SVGAII When Exists in PCI */ + if(SVGAIIExists) + videoDevice = VideoDriver.VMWareSVGAIIDriver; + + if (videoDevice == VideoDriver.VMWareSVGAIIDriver) + return MyVideoDriver = new SVGAIIScreen(mode); + else if (videoDevice == VideoDriver.VBEDriver) return MyVideoDriver = new VBEScreen(mode); /* We have already got a VideoDriver istance simple change its mode */ @@ -27,12 +42,9 @@ namespace Cosmos.System.Graphics public static Canvas GetFullScreenCanvas() { Global.mDebugger.SendInternal($"GetFullScreenCanvas() with default mode"); - if (MyVideoDriver == null) - return new VBEScreen(); - + /* We have already got a VideoDriver istance simple reset its mode to DefaultGraphicMode */ - MyVideoDriver.Mode = MyVideoDriver.DefaultGraphicMode; - return MyVideoDriver; + return GetFullScreenCanvas(MyVideoDriver.DefaultGraphicMode); } } } diff --git a/source/Cosmos.System2/Graphics/SVGAIIScreen.cs b/source/Cosmos.System2/Graphics/SVGAIIScreen.cs new file mode 100644 index 000000000..8c761a08a --- /dev/null +++ b/source/Cosmos.System2/Graphics/SVGAIIScreen.cs @@ -0,0 +1,189 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Cosmos.HAL.Drivers.PCI.Video; + +namespace Cosmos.System.Graphics +{ + public class SVGAIIScreen : Canvas + { + public VMWareSVGAII xSVGAIIDriver; + internal Debug.Kernel.Debugger mSVGAIIDebugger = new Debug.Kernel.Debugger("System", "SVGAIIScreen"); + + public SVGAIIScreen() : base() + { + mSVGAIIDebugger.SendInternal($"Creting new SVGAIIScreen with default mode {defaultGraphicMode}"); + + xSVGAIIDriver = new VMWareSVGAII(); + xSVGAIIDriver.SetMode((uint)defaultGraphicMode.Columns, (uint)defaultGraphicMode.Rows, (uint)defaultGraphicMode.ColorDepth); + } + + public SVGAIIScreen(Mode aMode) : base(aMode) + { + ThrowIfModeIsNotValid(aMode); + + xSVGAIIDriver = new VMWareSVGAII(); + xSVGAIIDriver.SetMode((uint)aMode.Columns, (uint)aMode.Rows, (uint)aMode.ColorDepth); + } + + public override Mode Mode + { + get => mode; + set + { + mode = value; + SetGraphicsMode(mode); + } + } + + public override void DrawPoint(Pen pen, int x, int y) + { + Color xColor = pen.Color; + + mSVGAIIDebugger.SendInternal($"Drawing point to x:{x}, y:{y} with {xColor.Name} Color"); + xSVGAIIDriver.SetPixel((uint)x, (uint)y, (uint)xColor.ToArgb()); + mSVGAIIDebugger.SendInternal($"Done drawing point"); + xSVGAIIDriver.Update(0, 0, (uint)mode.Columns, (uint)mode.Rows); + } + + public override void DrawPoint(Pen pen, float x, float y) + { + throw new NotImplementedException(); + } + + public override void DrawFilledRectangle(Pen pen, int x_start, int y_start, int width, int height) + { + xSVGAIIDriver.Fill((uint)x_start, (uint)y_start, (uint)width, (uint)height, (uint)pen.Color.ToArgb()); + } + + public override List getAvailableModes() + { + return new List + { + /* 16-bit Depth Resolutions*/ + + /* SD Resolutions */ + new Mode(320, 200, ColorDepth.ColorDepth16), + new Mode(320, 240, ColorDepth.ColorDepth16), + new Mode(640, 480, ColorDepth.ColorDepth16), + new Mode(720, 480, ColorDepth.ColorDepth16), + new Mode(800, 600, ColorDepth.ColorDepth16), + new Mode(1152, 768, ColorDepth.ColorDepth16), + + /* Old HD-Ready Resolutions */ + new Mode(1280, 720, ColorDepth.ColorDepth16), + new Mode(1280, 768, ColorDepth.ColorDepth16), + new Mode(1280, 800, ColorDepth.ColorDepth16), // WXGA + new Mode(1280, 1024, ColorDepth.ColorDepth16), // SXGA + + /* Better HD-Ready Resolutions */ + new Mode(1360, 768, ColorDepth.ColorDepth16), + new Mode(1366, 768, ColorDepth.ColorDepth16), // Original Laptop Resolution + new Mode(1440, 900, ColorDepth.ColorDepth16), // WXGA+ + new Mode(1400, 1050, ColorDepth.ColorDepth16), // SXGA+ + new Mode(1600, 1200, ColorDepth.ColorDepth16), // UXGA + new Mode(1680, 1050, ColorDepth.ColorDepth16), // WXGA++ + + /* HDTV Resolutions */ + new Mode(1920, 1080, ColorDepth.ColorDepth16), + new Mode(1920, 1200, ColorDepth.ColorDepth16), // WUXGA + + /* 2K Resolutions */ + new Mode(2048, 1536, ColorDepth.ColorDepth16), // QXGA + new Mode(2560, 1080, ColorDepth.ColorDepth16), // UW-UXGA + new Mode(2560, 1600, ColorDepth.ColorDepth16), // WQXGA + new Mode(2560, 2048, ColorDepth.ColorDepth16), // QXGA+ + new Mode(3200, 2048, ColorDepth.ColorDepth16), // WQXGA+ + new Mode(3200, 2400, ColorDepth.ColorDepth16), // QUXGA + new Mode(3840, 2400, ColorDepth.ColorDepth16), // WQUXGA + + /* 32-bit Depth Resolutions*/ + /* SD Resolutions */ + new Mode(320, 200, ColorDepth.ColorDepth32), + new Mode(320, 240, ColorDepth.ColorDepth32), + new Mode(640, 480, ColorDepth.ColorDepth32), + new Mode(720, 480, ColorDepth.ColorDepth32), + new Mode(800, 600, ColorDepth.ColorDepth32), + new Mode(1152, 768, ColorDepth.ColorDepth32), + + /* Old HD-Ready Resolutions */ + new Mode(1280, 720, ColorDepth.ColorDepth32), + new Mode(1280, 768, ColorDepth.ColorDepth32), + new Mode(1280, 800, ColorDepth.ColorDepth32), // WXGA + new Mode(1280, 1024, ColorDepth.ColorDepth32), // SXGA + + /* Better HD-Ready Resolutions */ + new Mode(1360, 768, ColorDepth.ColorDepth32), + new Mode(1366, 768, ColorDepth.ColorDepth32), // Original Laptop Resolution + new Mode(1440, 900, ColorDepth.ColorDepth32), // WXGA+ + new Mode(1400, 1050, ColorDepth.ColorDepth32), // SXGA+ + new Mode(1600, 1200, ColorDepth.ColorDepth32), // UXGA + new Mode(1680, 1050, ColorDepth.ColorDepth32), // WXGA++ + + /* HDTV Resolutions */ + new Mode(1920, 1080, ColorDepth.ColorDepth32), + new Mode(1920, 1200, ColorDepth.ColorDepth32), // WUXGA + + /* 2K Resolutions */ + new Mode(2048, 1536, ColorDepth.ColorDepth32), // QXGA + new Mode(2560, 1080, ColorDepth.ColorDepth32), // UW-UXGA + new Mode(2560, 1600, ColorDepth.ColorDepth32), // WQXGA + new Mode(2560, 2048, ColorDepth.ColorDepth32), // QXGA+ + new Mode(3200, 2048, ColorDepth.ColorDepth32), // WQXGA+ + new Mode(3200, 2400, ColorDepth.ColorDepth32), // QUXGA + new Mode(3840, 2400, ColorDepth.ColorDepth32), // WQUXGA + }; + } + + protected override Mode getDefaultGraphicMode() => new Mode(1024, 768, ColorDepth.ColorDepth16); + + private void SetGraphicsMode(Mode aMode) + { + ThrowIfModeIsNotValid(aMode); + + var xWidth = (uint)aMode.Columns; + var xHeight = (uint)aMode.Rows; + var xColorDepth = (uint)aMode.ColorDepth; + + xSVGAIIDriver.SetMode(xWidth, xHeight, xColorDepth); + } + + public override void Clear(Color color) + { + xSVGAIIDriver.Fill(0, 0, (uint)mode.Columns, (uint)mode.Rows, (uint)color.ToArgb()); + } + + public Color GetPixel(int aX, int aY) + { + var xColorARGB = xSVGAIIDriver.GetPixel((uint)aX, (uint)aX); + var xColor = Color.FromArgb((int)xColorARGB); + return xColor; + } + + public void SetCursor(bool aVisible, int aX, int aY) + { + xSVGAIIDriver.SetCursor(aVisible, (uint)aX, (uint)aY); + } + + public void CreateCursor() + { + xSVGAIIDriver.DefineCursor(); + } + + public void CopyPixel(int aX, int aY, int aNewX, int aNewY, int aWidth = 1, int aHeight = 1) + { + xSVGAIIDriver.Copy((uint)aX, (uint)aY, (uint)aNewX, (uint)aNewY, (uint)aWidth, (uint)aHeight); + } + + public void MovePixel(int aX, int aY, int aNewX, int aNewY) + { + xSVGAIIDriver.Copy((uint)aX, (uint)aY, (uint)aNewX, (uint)aNewY, 1, 1); + xSVGAIIDriver.SetPixel((uint)aX, (uint)aY, 0); + } + + public override Color GetPointColor(int x, int y) + { + return Color.FromArgb((int)xSVGAIIDriver.GetPixel((uint)x, (uint)y)); + } + } +} diff --git a/source/Cosmos.System2/Graphics/VBEScreen.cs b/source/Cosmos.System2/Graphics/VBEScreen.cs index d19544215..c95add72f 100644 --- a/source/Cosmos.System2/Graphics/VBEScreen.cs +++ b/source/Cosmos.System2/Graphics/VBEScreen.cs @@ -1,4 +1,4 @@ -//#define COSMOSDEBUG +//#define COSMOSDEBUG using Cosmos.HAL.Drivers; using System; using System.Collections.Generic; @@ -6,6 +6,7 @@ using System.Linq; using System.Text; using System.Threading.Tasks; using Cosmos.System.Graphics; +using Cosmos.Common.Extensions; namespace Cosmos.System { @@ -26,7 +27,7 @@ namespace Cosmos.System public VBEScreen(Mode mode) : base(mode) { - //Global.mDebugger.SendInternal($"Creating new VBEScreen() with mode {mode}"); + Global.mDebugger.SendInternal($"Creating new VBEScreen() with mode {mode.Columns}x{mode.Rows}x{(uint)mode.ColorDepth}"); ThrowIfModeIsNotValid(mode); @@ -128,9 +129,7 @@ namespace Cosmos.System * 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 + * ColorDepth.ColorDepth16 and ColorDepth.ColorDepth8 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) @@ -148,7 +147,18 @@ namespace Cosmos.System Global.mDebugger.SendInternal("Point drawn"); break; + case ColorDepth.ColorDepth24: + 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.R * 1000 + color.G) * 1000 + color.B)); + + Global.mDebugger.SendInternal("Point drawn"); + break; default: String errorMsg = "DrawPoint() with ColorDepth " + (int)Mode.ColorDepth + " not yet supported"; throw new NotImplementedException(errorMsg); @@ -184,7 +194,22 @@ namespace Cosmos.System #endregion #region Reading - // TODO add to Canvas GetPointColor() + public override Color GetPointColor(int x, int y) + { + uint pitch; + uint stride; + uint offset; + uint ColorDepthInBytes = (uint)mode.ColorDepth / 8; + + 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($"Getting color from point at offset {offset}"); + return Color.FromArgb(VBEDriver.GetVRAM(offset)); + } #endregion