-
Notifications
You must be signed in to change notification settings - Fork 0
Cosmos Graphic Revamp
The user of a Cosmos kernel should not know neither be interested on what driver is used to draw onto the screen, he simply should use a generic abstract system that only at low level (Ring 1 and Ring 0) interact with the hardware. To be clear this class / classes should permit to draw points, lines and rectangles on screen it is not intention of this work to create a widget toolkit neither this probably should be part of the Cosmos kernel instead this class / classes should be seen as an array of basic blocks similar at what lidgdi is on Windows and libcocoa on MacOS.
The possible color depth that a Mode could support: 4 bit (16 colors), 8 bit (256 colors), 16 bit (65535 colors) and 32 bit.
- ColorDepth4: 16 colors
- ColorDepth8: 256 colors
- ColorDepth16: 65535 colors
- ColorDepth24: 16 Millions of colors
- ColorDepth32: 16 Millions of colors + transparency
This represent a Video mode in the most generic and simple way: as the number of line per rows and a color dept.
- columns: get / set the number of lines (characters in text mode)
- rows: get / set the number of rows
- colordepth: the color depth used in this mode
- Mode(int columns, int rows, Colordepth colordepth): a simple constructor
- ToString() convert a Mode in its string representation
- Operator== it will be important for VBE3 to have the possibility to check if a Mode is equal to another
- Operator!= required if "==" is implemented
- GetHashCode() required for IEquatable interface
Why is this not simply an enum with the VESA predefined modes? Principally for two motivations:
- The VESA modes are defined until 1280x1024 and then no more. VESA suggests for VBE3 to query the Graphic card of the list of available modes and then search if the requested mode is valid. This is surely true for proprietary drivers too.
- Cosmos is tough to be portable and work on other architectures so using VESA modes would link us improperly to the PC architecture
This class represents an abstract canvas in which the user could define the size (an other way to see the mode) and draw inside of it. This is done on "imitation" of the System.Draw.Graphic and will use some objects that are defined for that as for example Color, Pen (conceptually the implementation is different) sadly it is impossible to plug it totally as the System.Draw.Graphic class presuppose the existence of form in which write but we are at the lower level. The Canvas is an abstract class that is to implement the Video drivers themselves and more higher level Canvas (for example Windows will be Canvas, sub-windows will be Canvas, Remote Desktop will be Canvas and so on...).
- mode: get / set the mode of the video card to mode. It throws if the selected mode is not supported by the video card
- defaultGraphicMode: default graphic mode this will change based on the underlying hardware
- Canvas Canvas(Mode mode) create a new Canvas with the mode specified
- List getAviableModes() returns the list of modes that the video card supports
- Clear(Color color: black) clear the entire Canvas using the specified color as background
- void DrawPoint(Pen pen, int x, int y) draws a point at the coordinates specified by x and y with the specified pen
- void DrawPoint(Pen pen, float x, float y) draws a point at the coordinates specified by x and y with the specified pen
- void DrawLine(Pen pen, int x_start, int y_start, int x_end, int y_end) draws a line at the coordinates specified by x_start, y_start and x_end, y_end with the specified pen
- void DrawLine(Pen pen, float x_start, float y_start, float x_end, float y_end) draws a line at the coordinates specified by x_start, y_start and x_end, y_end with the specified pen
- void DrawRectangle(Pen pen, int x_start, int y_start,int width, int height) draws a rectangle specified by a coordinate pair, a width, and a height with the specified pen
- void DrawRectangle(Pen pen, float x_start, float y_start, Single width, Single height) draws a rectangle specified by a coordinate pair, a width, and a height
- void DrawImage(Image, int x, int y) draws the specified Image, using its original physical size, at the specified location
- void DrawImage(Image, float x, float y) draws the specified Image, using its original physical size, at the specified location
- void DrawString(String, Font, Brush, int x, int y) draws the specified text string at the specified location with the specified Brush and Font objects. For now Brush will not have effect in the sense that the string will be always completely filled.
- void DrawString(String, Font, Brush, float x, float y) draws the specified text string at the specified location with the specified Brush and Font objects. For now Brush will not have effect in the sense that the string will be always completely filled.
Please note that in the abstract Canvas all this will have an implementation but it will be the more simple possible they should be overwritten by the specific driver implementation if a method could be accelerated (for example some Video card could have a method to directly draw a rectangle or an Image).
For now more "exotic" methods of the Graphic class will be not implemented (methods to draw polygons, to draw curves, ellipsis...). I see as more critical to implement DrawImage and DrawString the first one depends from the Image class (an abstraction of a bitmap) while the other will depend from Font and Brush while Brush could be a generic implementation as already said Font is a more high level concept that maybe is to the OS implementer to decide and not to be enforced by the kernel. Another possibility will be to left this method out of the Screen class in the end a String could be emulated creating an Image (a bitmap) in memory and then drawing that...
While will be possible to draw directly using the Canvas methods is more simple to use the Pen class so to define only one time the attributes of the object to draw.
- color: the color of the Pen
- width: the width of the Pen
other properties could be added (for example Brush) to change the aspect of the Pen (or better the objects that Pen draws).
- Pen(Canvas canvas, Color color: white, int width: 1): creates a Pen for the Canvas canvas with the specif color and widht. Throw if the Canvas is null, color is not valid for the Mode specified in Canvas or width is out of range
- void DrawPoint(int x, int y) draws a point at the coordinates specified by x and y with the specified pen
- void DrawPoint(float x, float y) draws a point at the coordinates specified by x and y with the specified pen
- void DrawLine(int x_start, int y_start, int x_end, int y_end) draws a line at the coordinates specified by x_start, y_start and x_end, y_end with the specified pen
- void DrawLine(float x_start, float y_start, float x_end, float y_end) draws a line at the coordinates specified by x_start, y_start and x_end, y_end with the specified pen
- void DrawRectangle(int x_start, int y_start, int width, int height) draws a rectangle specified by a coordinate pair, a width, and a height
- void DrawRectangle(float x_start, float y_start, float width, float height) draws a rectangle specified by a coordinate pair, a width, and a height
- void DrawImage(Image, int x, int y) draws the specified Image, using its original physical size, at the specified location
- void DrawImage(Image, float x, float y) draws the specified Image, using its original physical size, at the specified location
- void DrawString(String, Font, Brush,int x, int y) draws the specified text string at the specified location with the specified Brush and Font objects. For now Brush will not have effect in the sense that the string will be always completely filled.
- void DrawString(String, Font, Brush, float x, float y) draws the specified text string at the specified location with the specified Brush and Font objects. For now Brush will not have effect in the sense that the string will be always completely filled.
As it is not possible to instantiate directly a Canvas class from the user level (a Canvas in ring Hardware is the driver itself so it has already been instantiated by the kernel) a FullScreenCanvas class is created it inherits from the abstract Canvas class but it disables the Constructor (making it private) and has instead a static method GetFullScreenCanvas().
FullScreenCanvas is a simply proxy class that uses the Driver's Canvas instance to physically draw on the Video Card memory.
A Video driver will be represented by an instance of a Canvas class the difference is that creating a new Instance will initialize the Video Card and any of the DrawXXX functions will write directly onto the Video Card memory.
It is part of the work of the driver that implements the video driver to do the needed color conversions if the selected mode requires that (any mode that has no 32 bit color depth will need color conversions) the color conversion will simply select the same color from true color type contained in Color to the correspondent color depth specified in the Mode used the video driver, if no conversion exists it will throw. Doing dithering at this lower level is not the correct thing to do: it is expected to be part of the higher level implementation to do this.
The already existing drivers for VGA and Bochs (in VBE mode) should have to be changed to become implementer of the Canvas abstract class.
Possible problem: actually seems that VGA driver is always enabled in Cosmos and VBE driver runs on top of it, it is possible to do the correct thing that is to recognize that the Video Card is the Bochs one (SVGALib) and then start the Bochs driver in text mode? I suppose that the VGA ports to do text mode will be existing in any video card...
The VGA driver should be used only in the extreme case that the Video Card has no proprietary driver and VBE is not supported.