commit 96c3897cb8e3677a694e4e155f172ef11c86fdfb
parent 4823937d788aee780d28768fec2dcdae6f91d326
Author: Virgil Dupras <hsoft@hardcoded.net>
Date: Fri, 6 Jan 2023 20:54:47 -0500
gr/plane: add a layer of indirection
So, my old laptop has VESA 1.2, which means no linear buffer. I gotta do bank
switching. I'm preparing the field by adding new indirections in gr/plane to
make this possible.
Also, make .vesamodes show all modes and document vesa at doc/hw/i386/pc/vesa.
Diffstat:
4 files changed, 66 insertions(+), 21 deletions(-)
diff --git a/fs/doc/gr/plane.txt b/fs/doc/gr/plane.txt
@@ -34,6 +34,15 @@ Methods:
Allocate a new buffer of the proper size (considering height and pitch) and
set "buffer" to it.
+:addr ( self -- a )
+ Yield memory address corresponding to current position.
+
+:bytes< ( a u self -- )
+ Write u bytes from address a at current position.
+
+:bytes> ( a u self -- )
+ Write u bytes from current position at address a.
+
:pixel! ( self -- )
Set a pixel at tx,ty to the value of field "color".
diff --git a/fs/doc/hw/i386/pc/vesa.txt b/fs/doc/hw/i386/pc/vesa.txt
@@ -0,0 +1,32 @@
+# VESA
+
+VESA is the Video Electronics Standard Association and they created VBE, the
+VESA BIOS Extension standard. VESA 1.2 was released in 1991 and is the version
+that really caught on, so that's our baseline. VESA is much easier to work with
+than VGA, so that's why we prefer it.
+
+The driver lives in drv/pc/vesa.fs
+
+After you've loaded it, you can get general VESA information with ".vesa" and
+you can list available modes with ".vesamodes". The output is
+"<id> width/height/bpp". A "*" at the end indicates that this mode is a "linear"
+mode.
+
+There's a big difference between VESA 1.2 and VESA 2.0: the presence of linear
+buffer modes. A "regular" mode requires bank switching to access the totality of
+the memory for that mode, which comes in 64K banks. It's a hassle to manage.
+Linear modes provide a contiguous memory area, which is much nicer. When
+available, you always want linear mode, it's much faster.
+
+TODO: in fact, at this time, only linear mode is supported. bank switching
+support incoming...
+
+This driver provides the VESAScreen struct which you can instantiate and plug
+into the "screen" global variable from sys/screen. Example:
+
+ f<< /sys/screen.fs
+ f<< /drv/pc/vesa.fs
+ VESAScreen :new ' screen rebind
+
+The driver also has the "vesamode" variable, which defaults to $112
+(640x480x24), indicating which mode ID will be used on "screen :activate".
diff --git a/fs/drv/pc/vesa.fs b/fs/drv/pc/vesa.fs
@@ -80,14 +80,11 @@ here VBEModeInfo SZ allot structbind VBEModeInfo _curmode
( cx ) 0 $4f01 int10h ( di bx ax )
$4f = _assert drop ;
-\ To make the output a bit lighter, we ignore any mode that is not 24bpp or
-\ that don't support a linear frame buffer.
: _.mode ( mode -- )
dup >r _modeinfo >r \ V1=modeid V2=modeinfo
- r@ VBEModeInfo bpp 24 = r@ VBEModeInfo :linear? and if
- r@ VBEModeInfo bpp r@ VBEModeInfo height r> VBEModeInfo width
- r> .f" |%w %dx%dx%d "
- else rdrop rdrop then ;
+ r@ VBEModeInfo :linear?
+ r@ VBEModeInfo bpp r@ VBEModeInfo height r> VBEModeInfo width
+ r> .f" |%w %dx%dx%d" ( linear ) if '*' emit then spc> ;
\ We have to read all mode IDs before we call int10h because that list might be
\ overwritten by int10h.
diff --git a/fs/gr/plane.fs b/fs/gr/plane.fs
@@ -13,27 +13,34 @@ extends Rect struct[ Plane
sfield ty
sfield color
sfield buffer
+ smethod :addr ( self -- a )
+ smethod :bytes< ( a u self -- )
+ smethod :bytes> ( a u self -- )
: _colorbytes ( id -- nbytes ) colorbpp >> >> >> ;
+ : _xyoff ( x y self -- n )
+ tuck pitch * rot> encoding _colorbytes * + ;
+
+ : _addr ( self -- a )
+ dup buffer swap dup tx over ty rot _xyoff + ;
+
+ : _bytes< ( a u self -- ) _addr swap move ;
+ : _bytes> ( a u self -- ) _addr rot> move ;
+
: :new ( width height encoding -- plane )
>r >r >r 0 0 r> r> Rect :new ( rect )
r> ( encoding ) dup , _colorbytes over Rect width * ( pitch ) ,
- 0 ( tx ) , 0 ( ty ) , 0 ( color ) , 0 ( buffer ) , ;
+ 0 ( tx ) , 0 ( ty ) , 0 ( color ) , 0 ( buffer ) ,
+ ['] _addr , ['] _bytes< , ['] _bytes> , ;
: :allotbuf ( self -- ) >r \ V1=self
here r@ pitch r@ height * allot r> to buffer ;
- : _xyoff ( x y self -- n )
- tuck pitch * rot> encoding _colorbytes * + ;
-
: _rectaddr ( rect self -- )
tuck over x rot y ( self self x y )
rot _xyoff swap buffer + ;
- : _addr ( self -- a )
- dup buffer swap dup tx over ty rot _xyoff + ;
-
: :pixel! ( self -- ) >r \ V1=self
r@ color r@ _addr 16b !+ r> color 16 rshift swap c! ;
@@ -57,14 +64,14 @@ extends Rect struct[ Plane
2drop rdrop ;
: :copy< ( rect src self -- ) >r >r >r \ V1=self V2=src V3=rect
- V3 V2 _rectaddr V1 _addr V3 height >r begin ( srcaddr dstaddr )
- 2dup V3 width V1 encoding _colorbytes * ( src dst src dst u ) move
- V1 pitch + swap V2 pitch + swap next ( src dst )
- 2drop rfree ;
+ V3 V2 _rectaddr V3 height >r begin ( srcaddr )
+ dup V3 width V1 encoding _colorbytes * ( src src u ) V1 :bytes<
+ 1 V1 :ty+ V2 pitch + next ( src )
+ drop rfree ;
: :copy> ( rect dst self -- ) >r >r >r \ V1=self V2=dst V3=rect
- V1 _addr V3 V2 _rectaddr V3 height >r begin ( srcaddr dstaddr )
- 2dup V3 width V1 encoding _colorbytes * ( src dst src dst u ) move
- V2 pitch + swap V1 pitch + swap next ( src dst )
- 2drop rfree ;
+ V3 V2 _rectaddr V3 height >r begin ( dstaddr )
+ dup V3 width V1 encoding _colorbytes * ( dst dst u ) V1 :bytes>
+ 1 V1 :ty+ V2 pitch + next ( dst )
+ drop rfree ;
]struct