From 56f357ade393dc9e2c928971cfbd690dab72db18 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sat, 24 Apr 2010 23:38:02 +0800 Subject: [PATCH] Added basic 2D video accelleration --- Kernel/Makefile.BuildNum | 2 +- Kernel/drv/vterm.c | 51 +++++++++++-- Kernel/drvutil.c | 74 +++++++++++++++++++ Kernel/include/tpl_drv_video.h | 48 ++++++++++++ Modules/Display/VESA/main.c | 71 ++++++++++++++++++ .../Applications/axwin2_src/WM/interface.c | 7 +- 6 files changed, 246 insertions(+), 7 deletions(-) diff --git a/Kernel/Makefile.BuildNum b/Kernel/Makefile.BuildNum index 0deb19f8..0c5bde4f 100644 --- a/Kernel/Makefile.BuildNum +++ b/Kernel/Makefile.BuildNum @@ -1 +1 @@ -BUILD_NUM = 2057 +BUILD_NUM = 2070 diff --git a/Kernel/drv/vterm.c b/Kernel/drv/vterm.c index 8255f6c7..ab1e97d1 100644 --- a/Kernel/drv/vterm.c +++ b/Kernel/drv/vterm.c @@ -77,6 +77,7 @@ void VT_KBCallBack(Uint32 Codepoint); void VT_int_PutString(tVTerm *Term, Uint8 *Buffer, Uint Count); int VT_int_ParseEscape(tVTerm *Term, char *Buffer); void VT_int_PutChar(tVTerm *Term, Uint32 Ch); +void VT_int_ScrollFramebuffer( tVTerm *Term ); void VT_int_UpdateScreen( tVTerm *Term, int UpdateAll ); void VT_int_ChangeMode(tVTerm *Term, int NewMode); @@ -920,13 +921,13 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch) Term->WritePos ++; break; } - // Move Screen if(Term->WritePos >= Term->Width*Term->Height*VT_SCROLLBACK) { int base, i; Term->WritePos -= Term->Width; + VT_int_UpdateScreen( Term, 0 ); // Update view position base = Term->Width*Term->Height*(VT_SCROLLBACK-1); @@ -951,18 +952,58 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch) } //LOG("Scrolled buffer"); - VT_int_UpdateScreen( Term, 1 ); + VT_int_ScrollFramebuffer( Term ); + VT_int_UpdateScreen( Term, 0 ); } - else if(Term->WritePos >= Term->Width*Term->Height+Term->ViewPos) + else if(Term->WritePos >= Term->ViewPos + Term->Width*Term->Height) { - Term->ViewPos += Term->Width; //LOG("Scrolled screen"); - VT_int_UpdateScreen( Term, 1 ); + Term->WritePos -= Term->Width; + VT_int_UpdateScreen( Term, 0 ); + Term->WritePos += Term->Width; + + Term->ViewPos += Term->Width; + VT_int_ScrollFramebuffer( Term ); + VT_int_UpdateScreen( Term, 0 ); } //LEAVE('-'); } +/** + * \fn void VT_int_ScrollFramebuffer( tVTerm *Term ) + * \note Scrolls the framebuffer by 1 text line + */ +void VT_int_ScrollFramebuffer( tVTerm *Term ) +{ + int tmp; + struct { + Uint8 Op; + Uint16 DstX, DstY; + Uint16 SrcX, SrcY; + Uint16 W, H; + } PACKED buf; + // Only update if this is the current terminal + if( Term != gpVT_CurTerm ) return; + + // This should only be called in text mode + + tmp = VIDEO_BUFFMT_2DSTREAM; + VFS_IOCtl(giVT_OutputDevHandle, VIDEO_IOCTL_SETBUFFORMAT, &tmp); + + buf.Op = VIDEO_2DOP_BLIT; + buf.DstX = 0; buf.DstY = 0; + buf.SrcX = 0; buf.SrcY = giVT_CharHeight; + buf.W = Term->Width * giVT_CharWidth; + buf.H = (Term->Height-1) * giVT_CharHeight; + + VFS_WriteAt(giVT_OutputDevHandle, 0, 1+12, &buf); + + // Restore old mode + tmp = VIDEO_BUFFMT_TEXT; + VFS_IOCtl(giVT_OutputDevHandle, VIDEO_IOCTL_SETBUFFORMAT, &tmp); +} + /** * \fn void VT_int_UpdateScreen( tVTerm *Term, int UpdateAll ) * \brief Updates the video framebuffer diff --git a/Kernel/drvutil.c b/Kernel/drvutil.c index 12f21cd9..99d02f62 100644 --- a/Kernel/drvutil.c +++ b/Kernel/drvutil.c @@ -5,8 +5,82 @@ #define DEBUG 0 #include #include +#include // === CODE === +// --- Video Driver Helpers --- +Uint64 DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length, + tDrvUtil_Video_2DHandlers *Handlers, int SizeofHandlers) +{ + Uint8 *stream = Buffer; + int rem = Length; + int op; + while( rem ) + { + rem --; + op = *stream++; + + if(op > NUM_VIDEO_2DOPS) { + Log_Warning("DrvUtil", "DrvUtil_Video_2DStream: Unknown" + " operation %i", op); + } + + if(op*4 > SizeofHandlers) { + Log_Warning("DrvUtil", "DrvUtil_Video_2DStream: Driver does" + " not support op %i", op); + return Length-rem; + } + + switch(op) + { + case VIDEO_2DOP_NOP: break; + + case VIDEO_2DOP_FILL: + if(rem < 12) return Length-rem; + + if(!Handlers->Fill) { + Log_Warning("DrvUtil", "DrvUtil_Video_2DStream: Driver" + " does not support VIDEO_2DOP_FILL"); + return Length-rem; + } + + Handlers->Fill( + Ent, + *(Uint16*)(&stream[0]), *(Uint16*)(&stream[2]), + *(Uint16*)(&stream[4]), *(Uint16*)(&stream[6]), + *(Uint32*)(&stream[8]) + ); + + rem -= 12; + stream += 12; + break; + + case VIDEO_2DOP_BLIT: + if(rem < 12) return Length-rem; + + if(!Handlers->Blit) { + Log_Warning("DrvUtil", "DrvUtil_Video_2DStream: Driver" + " does not support VIDEO_2DOP_BLIT"); + return Length-rem; + } + + Handlers->Blit( + Ent, + *(Uint16*)(&stream[0]), *(Uint16*)(&stream[2]), + *(Uint16*)(&stream[4]), *(Uint16*)(&stream[6]), + *(Uint16*)(&stream[8]), *(Uint16*)(&stream[10]) + ); + + rem -= 12; + stream += 12; + break; + + } + } + return 0; +} + +// --- Disk Driver Helpers --- Uint64 DrvUtil_ReadBlock(Uint64 Start, Uint64 Length, void *Buffer, tDrvUtil_Callback ReadBlocks, Uint64 BlockSize, Uint Argument) { diff --git a/Kernel/include/tpl_drv_video.h b/Kernel/include/tpl_drv_video.h index ce575bb7..89bdbfd8 100644 --- a/Kernel/include/tpl_drv_video.h +++ b/Kernel/include/tpl_drv_video.h @@ -159,6 +159,38 @@ enum eTplVideo_BufFormats VIDEO_BUFFMT_3DSTREAM }; +/** + * \brief + */ +enum eTplVideo_2DCommands +{ + /** + * \brief No Operation + */ + VIDEO_2DOP_NOP, + /** + * \brief Fill a region + * \param X Uint16 - Leftmost pixels of the region + * \param Y Uint16 - Topmost pixels of the region + * \param W Uint16 - Width of the region + * \param H Uint16 - Height of the region + * \param Colour Uint32 - Value to fill with + */ + VIDEO_2DOP_FILL, + /** + * \brief Copy a region from one part of the framebuffer to another + * \param DestX Uint16 - Leftmost pixels of the destination + * \param DestY Uint16 - Topmost pixels of the destination + * \param SrcX Uint16 - Leftmost pixels of the source + * \param SrcY Uint16 - Topmost pixels of the source + * \param Width Uint16 - Width of the region + * \param Height Uint16 - Height of the region + */ + VIDEO_2DOP_BLIT, + + NUM_VIDEO_2DOPS +}; + /** * \brief Describes a position in the video framebuffer */ @@ -221,4 +253,20 @@ extern void VT_Font_Render(Uint32 Codepoint, void *Buffer, int Pitch, Uint32 BGC */ extern Uint32 VT_Colour12to24(Uint16 Col12); +/** + * + */ +typedef struct sDrvUtil_Video_2DHandlers +{ + void *Nop; + void (*Fill)(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour); + void (*Blit)(void *Ent, Uint16 DestX, Uint16 DestY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H); +} tDrvUtil_Video_2DHandlers; + +/** + * \brief + */ +extern Uint64 DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length, + tDrvUtil_Video_2DHandlers *Handlers, int SizeofHandlers); + #endif diff --git a/Modules/Display/VESA/main.c b/Modules/Display/VESA/main.c index 85bcb3b5..a4f346f3 100644 --- a/Modules/Display/VESA/main.c +++ b/Modules/Display/VESA/main.c @@ -25,6 +25,9 @@ Uint64 Vesa_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); int Vesa_Int_SetMode(int Mode); int Vesa_Int_FindMode(tVideo_IOCtl_Mode *data); int Vesa_Int_ModeInfo(tVideo_IOCtl_Mode *data); +// --- 2D Acceleration Functions -- +void Vesa_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour); +void Vesa_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H); // === GLOBALS === MODULE_DEFINE(0, VERSION, Vesa, Vesa_Install, NULL, "PCI", "VM8086", NULL); @@ -45,6 +48,11 @@ char *gpVesa_Framebuffer = (void*)VESA_DEFAULT_FRAMEBUFFER; tVesa_Mode *gVesa_Modes; int giVesaModeCount = 0; int giVesaPageCount = 0; +tDrvUtil_Video_2DHandlers gVesa_2DFunctions = { + NULL, + Vesa_2D_Fill, + Vesa_2D_Blit +}; //CODE int Vesa_Install(char **Arguments) @@ -291,6 +299,14 @@ Uint64 Vesa_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) LOG("BGA Framebuffer updated"); } break; + + case VIDEO_BUFFMT_2DSTREAM: + Length = DrvUtil_Video_2DStream( + NULL, // Single framebuffer, so Ent is unused + Buffer, Length, &gVesa_2DFunctions, sizeof(gVesa_2DFunctions) + ); + break; + default: LEAVE('i', -1); return -1; @@ -429,3 +445,58 @@ int Vesa_Int_ModeInfo(tVideo_IOCtl_Mode *data) data->bpp = gVesa_Modes[data->id].bpp; return 1; } + +// ------------------------ +// --- 2D Accelleration --- +// ------------------------ +void Vesa_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour) +{ + int scrnwidth = gVesa_Modes[giVesaCurrentMode].width; + Uint32 *buf = (Uint32*)gpVesa_Framebuffer + Y*scrnwidth + X; + while( H -- ) { + memsetd(buf, Colour, W); + buf += scrnwidth; + } +} + +void Vesa_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H) +{ + int scrnwidth = gVesa_Modes[giVesaCurrentMode].width; + int dst = DstY*scrnwidth + DstX; + int src = SrcY*scrnwidth + SrcX; + int tmp; + + //Log("Vesa_2D_Blit: (Ent=%p, DstX=%i, DstY=%i, SrcX=%i, SrcY=%i, W=%i, H=%i)", + // Ent, DstX, DstY, SrcX, SrcY, W, H); + + if(SrcX + W > scrnwidth) + W = scrnwidth - SrcX; + if(DstX + W > scrnwidth) + W = scrnwidth - DstX; + if(SrcY + H > gVesa_Modes[giVesaCurrentMode].height) + H = gVesa_Modes[giVesaCurrentMode].height - SrcY; + if(DstY + H > gVesa_Modes[giVesaCurrentMode].height) + H = gVesa_Modes[giVesaCurrentMode].height - DstY; + + if( dst > src ) { + // Reverse copy + dst += H*scrnwidth; + src += H*scrnwidth; + while( H -- ) { + dst -= scrnwidth; + src -= scrnwidth; + tmp = W; + for( tmp = W; tmp --; ) { + *((Uint32*)gpVesa_Framebuffer + dst + tmp) = *((Uint32*)gpVesa_Framebuffer + src + tmp); + } + } + } + else { + // Normal copy is OK + while( H -- ) { + memcpyd((Uint32*)gpVesa_Framebuffer + dst, (Uint32*)gpVesa_Framebuffer + src, W); + dst += scrnwidth; + src += scrnwidth; + } + } +} diff --git a/Usermode/Applications/axwin2_src/WM/interface.c b/Usermode/Applications/axwin2_src/WM/interface.c index 36e0124e..4d22b50f 100644 --- a/Usermode/Applications/axwin2_src/WM/interface.c +++ b/Usermode/Applications/axwin2_src/WM/interface.c @@ -4,12 +4,17 @@ */ #include "common.h" +// === GLOBALS == + int giInterface_Width = 0; + // === CODE === void Interface_Render(void) { + giInterface_Width = giScreenWidth/16; + Video_FillRect( 0, 0, - giScreenWidth/16, giScreenHeight, + giInterface_Width, giScreenHeight, 0xDDDDDD); Video_Update(); -- 2.20.1