Kernel/drvutil - Adding software cursor support
authorJohn Hodge <[email protected]>
Tue, 18 Oct 2011 10:59:07 +0000 (18:59 +0800)
committerJohn Hodge <[email protected]>
Tue, 18 Oct 2011 10:59:07 +0000 (18:59 +0800)
Kernel/drvutil.c
Kernel/include/api_drv_video.h

index c55cd92..8908e7e 100644 (file)
@@ -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;
index 28b9854..8419db2 100644 (file)
@@ -295,6 +295,15 @@ extern Uint32      VT_Colour12toN(Uint16 Col12, int Depth);
 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
@@ -311,15 +320,41 @@ struct sDrvUtil_Video_BufInfo
        /**\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
@@ -377,6 +412,33 @@ extern int DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length,
  * \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

UCC git Repository :: git.ucc.asn.au