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;
typedef struct sDrvUtil_Video_BufInfo tDrvUtil_Video_BufInfo;\r
typedef struct sDrvUtil_Video_2DHandlers tDrvUtil_Video_2DHandlers;\r
\r
+/**\r
+ * \brief Maximum cursor width for using the DrvUtil software cursor\r
+ */\r
+#define DRVUTIL_MAX_CURSOR_W 32\r
+/**\r
+ * \brief Maximum cursor width for using the DrvUtil software cursor\r
+ */\r
+#define DRVUTIL_MAX_CURSOR_H 32\r
+\r
/**\r
* \brief Framebuffer information used by all DrvUtil_Video functions\r
*/\r
/**\r
* \brief Number of pixels in each line\r
*/\r
- int Width;\r
+ short Width;\r
/**\r
* \brief Total number of lines\r
*/\r
- int Height;\r
+ short Height;\r
/**\r
* \brief Bit depth of the framebuffer\r
*/\r
int Depth;\r
+ \r
+ /**\r
+ * \brief Software cursor controls\r
+ * \{\r
+ */\r
+ /**\r
+ * \brief X coordinate of the cursor\r
+ */\r
+ short CursorX;\r
+ /**\r
+ * \brief Y coordinate of the cursor\r
+ */\r
+ short CursorY;\r
+\r
+ /**\r
+ * \brief Cursor bitmap\r
+ */\r
+ tVideo_IOCtl_Bitmap *CursorBitmap;\r
+\r
+ /**\r
+ * \brief Buffer to store the area under the cursor\r
+ */\r
+ void *CursorSaveBuf;\r
+ /*\r
+ * \}\r
+ */\r
};\r
\r
/**\r
* \return Number of bytes written\r
*\r
* Handles all write modes in software, using the VT font calls for rendering.\r
+ * \note Calls the cursor clear and redraw if the cursor area is touched\r
*/\r
extern int DrvUtil_Video_WriteLFB(int Mode, tDrvUtil_Video_BufInfo *FBInfo, size_t Offset, size_t Length, void *Src);\r
+\r
+/**\r
+ * \brief Software cursor rendering\r
+ * \{\r
+ */\r
+/**\r
+ * \brief Set the cursor bitmap for a buffer\r
+ * \param Buf Framebuffer descriptor\r
+ * \param Bitmap New cursor bitmap\r
+ */\r
+extern void DrvUtil_Video_SetCursor(tDrvUtil_Video_BufInfo *Buf, tVideo_IOCtl_Bitmap *Bitmap);\r
+/**\r
+ * \brief Render the cursor at (\a X, \a Y)\r
+ * \param Buf Framebuffer descriptor, see type for details\r
+ * \param X X coord of the cursor\r
+ * \param Y Y coord of the cursor\r
+ */\r
+extern void DrvUtil_Video_DrawCursor(tDrvUtil_Video_BufInfo *Buf, int X, int Y);\r
+/**\r
+ * \brief Removes the rendered cursor from the screen\r
+ * \param Buf Framebuffer descriptor, see type for details\r
+ */\r
+extern void DrvUtil_Video_RemoveCursor(tDrvUtil_Video_BufInfo *Buf);\r
+/**\r
+ * \}\r
+ */\r
#endif\r