From: John Hodge Date: Tue, 18 Oct 2011 10:59:07 +0000 (+0800) Subject: Kernel/drvutil - Adding software cursor support X-Git-Tag: rel0.13~38 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=b071471491867030e7c8b61790c71c0a38cfea2d;p=tpg%2Facess2.git Kernel/drvutil - Adding software cursor support --- diff --git a/Kernel/drvutil.c b/Kernel/drvutil.c index c55cd929..8908e7e3 100644 --- a/Kernel/drvutil.c +++ b/Kernel/drvutil.c @@ -203,6 +203,125 @@ int DrvUtil_Video_WriteLFB(int Mode, tDrvUtil_Video_BufInfo *FBInfo, size_t Offs return Length; } +void DrvUtil_Video_SetCursor(tDrvUtil_Video_BufInfo *Buf, tVideo_IOCtl_Bitmap *Bitmap) +{ + int csrX = Buf->CursorX, csrY = Buf->CursorY; + size_t size; + + // Clear old bitmap + if( Buf->CursorBitmap ) + { + DrvUtil_Video_RemoveCursor(Buf); + if( Bitmap->W != Buf->CursorBitmap->W || Bitmap->H != Buf->CursorBitmap->H ) + { + free( Buf->CursorSaveBuf ); + Buf->CursorSaveBuf = NULL; + } + free(Buf->CursorBitmap); + Buf->CursorBitmap = NULL; + } + + // Check the new bitmap is valid + size = sizeof(tVideo_IOCtl_Bitmap) + Bitmap->W*Bitmap->H*4; + if( !CheckMem(Bitmap, size) ) { + Log_Warning("DrvUtil", "DrvUtil_Video_SetCursor: Bitmap (%p) invalid mem", Bitmap); + return; + } + + // Take a copy + Buf->CursorBitmap = malloc( size ); + memcpy(Buf->CursorBitmap, Bitmap, size); + + // Restore cursor position + DrvUtil_Video_DrawCursor(Buf, csrX, csrY); +} + +void DrvUtil_Video_DrawCursor(tDrvUtil_Video_BufInfo *Buf, int X, int Y) +{ + int bytes_per_px = (Buf->Depth + 7) / 8; + Uint32 *dest, *src; + int save_pitch, y; + int render_ox=0, render_oy=0, render_w, render_h; + + if( X < 0 || Y < 0 ) return; + if( X >= Buf->Width || Y >= Buf->Height ) return; + + if( !Buf->CursorBitmap ) return ; + + X -= Buf->CursorBitmap->XOfs; + Y -= Buf->CursorBitmap->YOfs; + + render_w = X > Buf->Width - Buf->CursorBitmap->W ? Buf->Width - X : Buf->CursorBitmap->W; + render_h = Y > Buf->Height - Buf->CursorBitmap->H ? Buf->Height - Y : Buf->CursorBitmap->H; + + if(X < 0) { + render_ox = -X; + X = 0; + } + if(Y < 0) { + render_oy = -Y; + Y = 0; + } + + save_pitch = Buf->CursorBitmap->W * bytes_per_px; + + dest = (void*)( (tVAddr)Buf->Framebuffer + Y * Buf->Pitch + X*bytes_per_px ); + src = Buf->CursorBitmap->Data; + if( !Buf->CursorSaveBuf ) + Buf->CursorSaveBuf = malloc( Buf->CursorBitmap->W*Buf->CursorBitmap->H*bytes_per_px ); + // Save behind the cursor + for( y = render_oy; y < render_h; y ++ ) + memcpy( + (Uint8*)Buf->CursorSaveBuf + y*save_pitch, + (Uint8*)dest + render_ox*bytes_per_px + y*Buf->Pitch, + render_w*bytes_per_px + ); + // Draw the cursor + switch(Buf->Depth) + { + case 32: + src += render_oy * Buf->CursorBitmap->W; + for( y = render_oy; y < render_h; y ++ ) + { + int x; + for(x = render_ox; x < render_w; x ++ ) + { + if(src[x] & 0xFF000000) + dest[x] = src[x]; + else + ; // NOP, completely transparent + } + src += Buf->CursorBitmap->W; + dest = (void*)((Uint8*)dest + Buf->Pitch); + } + break; + default: + Log_Error("DrvUtil", "TODO: Implement non 32-bpp cursor"); + break; + } + Buf->CursorX = X; + Buf->CursorY = Y; +} + +void DrvUtil_Video_RemoveCursor(tDrvUtil_Video_BufInfo *Buf) +{ + int bytes_per_px = (Buf->Depth + 7) / 8; + int y, save_pitch; + Uint32 *dest; + + if( !Buf->CursorBitmap || Buf->CursorX == -1 ) return ; + + if( !Buf->CursorSaveBuf ) + return ; + + save_pitch = Buf->CursorBitmap->W * bytes_per_px; + dest = (void*)( (tVAddr)Buf->Framebuffer + Buf->CursorY * Buf->Pitch + Buf->CursorX*bytes_per_px ); + for( y = 0; y < Buf->CursorBitmap->H; y ++ ) + memcpy( (Uint8*)dest + y*Buf->Pitch, (Uint8*)Buf->CursorSaveBuf + y*save_pitch, save_pitch); + + Buf->CursorX = -1; +} + void DrvUtil_Video_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour) { tDrvUtil_Video_BufInfo *FBInfo = Ent; diff --git a/Kernel/include/api_drv_video.h b/Kernel/include/api_drv_video.h index 28b98542..8419db21 100644 --- a/Kernel/include/api_drv_video.h +++ b/Kernel/include/api_drv_video.h @@ -295,6 +295,15 @@ extern Uint32 VT_Colour12toN(Uint16 Col12, int Depth); typedef struct sDrvUtil_Video_BufInfo tDrvUtil_Video_BufInfo; typedef struct sDrvUtil_Video_2DHandlers tDrvUtil_Video_2DHandlers; +/** + * \brief Maximum cursor width for using the DrvUtil software cursor + */ +#define DRVUTIL_MAX_CURSOR_W 32 +/** + * \brief Maximum cursor width for using the DrvUtil software cursor + */ +#define DRVUTIL_MAX_CURSOR_H 32 + /** * \brief Framebuffer information used by all DrvUtil_Video functions */ @@ -311,15 +320,41 @@ struct sDrvUtil_Video_BufInfo /** * \brief Number of pixels in each line */ - int Width; + short Width; /** * \brief Total number of lines */ - int Height; + short Height; /** * \brief Bit depth of the framebuffer */ int Depth; + + /** + * \brief Software cursor controls + * \{ + */ + /** + * \brief X coordinate of the cursor + */ + short CursorX; + /** + * \brief Y coordinate of the cursor + */ + short CursorY; + + /** + * \brief Cursor bitmap + */ + tVideo_IOCtl_Bitmap *CursorBitmap; + + /** + * \brief Buffer to store the area under the cursor + */ + void *CursorSaveBuf; + /* + * \} + */ }; /** @@ -377,6 +412,33 @@ extern int DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length, * \return Number of bytes written * * Handles all write modes in software, using the VT font calls for rendering. + * \note Calls the cursor clear and redraw if the cursor area is touched */ extern int DrvUtil_Video_WriteLFB(int Mode, tDrvUtil_Video_BufInfo *FBInfo, size_t Offset, size_t Length, void *Src); + +/** + * \brief Software cursor rendering + * \{ + */ +/** + * \brief Set the cursor bitmap for a buffer + * \param Buf Framebuffer descriptor + * \param Bitmap New cursor bitmap + */ +extern void DrvUtil_Video_SetCursor(tDrvUtil_Video_BufInfo *Buf, tVideo_IOCtl_Bitmap *Bitmap); +/** + * \brief Render the cursor at (\a X, \a Y) + * \param Buf Framebuffer descriptor, see type for details + * \param X X coord of the cursor + * \param Y Y coord of the cursor + */ +extern void DrvUtil_Video_DrawCursor(tDrvUtil_Video_BufInfo *Buf, int X, int Y); +/** + * \brief Removes the rendered cursor from the screen + * \param Buf Framebuffer descriptor, see type for details + */ +extern void DrvUtil_Video_RemoveCursor(tDrvUtil_Video_BufInfo *Buf); +/** + * \} + */ #endif