Kernel - Slight reworks to timer code
[tpg/acess2.git] / Kernel / drvutil.c
index fb9a103..d19a050 100644 (file)
@@ -1,6 +1,9 @@
 /*
- * Acess2
- * Common Driver/Filesystem Helper Functions
+ * Acess2 Kernel
+ * - By John Hodge
+ *
+ * drvutil.c
+ * - Common Driver/Filesystem Helper Functions
  */
 #define DEBUG  0
 #include <acess.h>
 // === PROTOTYPES ===
 //int  DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length, tDrvUtil_Video_2DHandlers *Handlers, int SizeofHandlers);
 //size_t       DrvUtil_Video_WriteLFB(int Mode, tDrvUtil_Video_BufInfo *FBInfo, size_t Offset, size_t Length, void *Src);
+//void DrvUtil_Video_SetCursor(tDrvUtil_Video_BufInfo *Buf, tVideo_IOCtl_Bitmap *Bitmap);
+//void DrvUtil_Video_DrawCursor(tDrvUtil_Video_BufInfo *Buf, int X, int Y);
+void   DrvUtil_Video_RenderCursor(tDrvUtil_Video_BufInfo *Buf);
+//void DrvUtil_Video_RemoveCursor(tDrvUtil_Video_BufInfo *Buf);
 void   DrvUtil_Video_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour);
 void   DrvUtil_Video_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H);
 
@@ -21,20 +28,42 @@ tDrvUtil_Video_2DHandlers   gDrvUtil_Stub_2DFunctions = {
        DrvUtil_Video_2D_Fill,
        DrvUtil_Video_2D_Blit
 };
+tVideo_IOCtl_Bitmap    gDrvUtil_TextModeCursor = {
+       8, 16,
+       0, 0,
+       {
+               0, 0, 0         , 0, 0, 0, 0, 0,
+               0,-1, 0xFF000000, 0, 0, 0, 0, 0,
+               0,-1, 0xFF000000, 0, 0, 0, 0, 0,
+               0,-1, 0xFF000000, 0, 0, 0, 0, 0,
+               0,-1, 0xFF000000, 0, 0, 0, 0, 0,
+               0,-1, 0xFF000000, 0, 0, 0, 0, 0,
+               0,-1, 0xFF000000, 0, 0, 0, 0, 0,
+               0,-1, 0xFF000000, 0, 0, 0, 0, 0,
+               0,-1, 0xFF000000, 0, 0, 0, 0, 0,
+               0,-1, 0xFF000000, 0, 0, 0, 0, 0,
+               0,-1, 0xFF000000, 0, 0, 0, 0, 0,
+               0,-1, 0xFF000000, 0, 0, 0, 0, 0,
+               0,-1, 0xFF000000, 0, 0, 0, 0, 0,
+               0,-1, 0xFF000000, 0, 0, 0, 0, 0,
+               0, 0, 0         , 0, 0, 0, 0, 0,
+               0, 0, 0         , 0, 0, 0, 0, 0
+       }
+};
 
 // === CODE ===
 // --- Video Driver Helpers ---
-int DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length,
+int DrvUtil_Video_2DStream(void *Ent, const void *Buffer, int Length,
        tDrvUtil_Video_2DHandlers *Handlers, int SizeofHandlers)
 {
-       void    *stream = Buffer;
+       const Uint8     *stream = Buffer;
         int    rem = Length;
         int    op;
        while( rem )
        {
                rem --;
-               op = *(Uint8*)stream;
-               stream = (void*)((tVAddr)stream + 1);
+               op = *stream;
+               stream ++;
                
                if(op > NUM_VIDEO_2DOPS) {
                        Log_Warning("DrvUtil",
@@ -55,7 +84,7 @@ int DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length,
                case VIDEO_2DOP_NOP:    break;
                
                case VIDEO_2DOP_FILL:
-                       if(rem < 12)    return Length-rem;
+                       if(rem < 10)    return Length-rem;
                        
                        if(!Handlers->Fill) {
                                Log_Warning("DrvUtil", "DrvUtil_Video_2DStream: Driver"
@@ -65,13 +94,13 @@ int DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length,
                        
                        Handlers->Fill(
                                Ent,
-                               ((Uint16*)stream)[0], ((Uint16*)stream)[1],
-                               ((Uint16*)stream)[2], ((Uint16*)stream)[3],
-                               ((Uint32*)stream)[2]
+                               ((const Uint16*)stream)[0], ((const Uint16*)stream)[1],
+                               ((const Uint16*)stream)[2], ((const Uint16*)stream)[3],
+                               ((const Uint32*)stream)[4]
                                );
                        
-                       rem -= 12;
-                       stream = (void*)((tVAddr)stream + 12);
+                       rem -= 10;
+                       stream += 10;
                        break;
                
                case VIDEO_2DOP_BLIT:
@@ -85,13 +114,13 @@ int DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length,
                        
                        Handlers->Blit(
                                Ent,
-                               ((Uint16*)stream)[0], ((Uint16*)stream)[1],
-                               ((Uint16*)stream)[2], ((Uint16*)stream)[3],
-                               ((Uint16*)stream)[4], ((Uint16*)stream)[5]
+                               ((const Uint16*)stream)[0], ((const Uint16*)stream)[1],
+                               ((const Uint16*)stream)[2], ((const Uint16*)stream)[3],
+                               ((const Uint16*)stream)[4], ((const Uint16*)stream)[5]
                                );
                        
                        rem -= 12;
-                       stream = (void*)((tVAddr)stream + 12);
+                       stream += 12;
                        break;
                
                }
@@ -99,20 +128,29 @@ int DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length,
        return 0;
 }
 
-int DrvUtil_Video_WriteLFB(tDrvUtil_Video_BufInfo *FBInfo, size_t Offset, size_t Length, void *Buffer)
+int DrvUtil_Video_WriteLFB(tDrvUtil_Video_BufInfo *FBInfo, size_t Offset, size_t Length, const void *Buffer)
 {
        Uint8   *dest;
+       const Uint32    *src = Buffer;
+        int    csr_x, csr_y;
+        int    x, y;
+        int    bytes_per_px = (FBInfo->Depth + 7) / 8;
        ENTER("pFBInfo xOffset xLength pBuffer",
                Mode, FBInfo, Offset, Length, Buffer);
+
+       csr_x = FBInfo->CursorX;
+       csr_y = FBInfo->CursorY;
+
+       DrvUtil_Video_RemoveCursor(FBInfo);
+
        switch( FBInfo->BufferFormat )
        {
        case VIDEO_BUFFMT_TEXT:
                {
-               tVT_Char        *chars = Buffer;
-                int    bytes_per_px = (FBInfo->Depth + 7) / 8;
+               const tVT_Char  *chars = Buffer;
                 int    widthInChars = FBInfo->Width/giVT_CharWidth;
                 int    heightInChars = FBInfo->Height/giVT_CharHeight;
-                int    x, y, i;
+                int    i;
        
                LOG("bytes_per_px = %i", bytes_per_px);
                LOG("widthInChars = %i, heightInChars = %i", widthInChars, heightInChars);
@@ -144,9 +182,6 @@ int DrvUtil_Video_WriteLFB(tDrvUtil_Video_BufInfo *FBInfo, size_t Offset, size_t
                                break;
                        }
 
-//                     LOG("chars->Ch=0x%x,chars->BGCol=0x%x,chars->FGCol=0x%x",
-//                             chars->Ch, chars->BGCol, chars->FGCol);         
-
                        VT_Font_Render(
                                chars->Ch,
                                dest + x*giVT_CharWidth*bytes_per_px, FBInfo->Depth, FBInfo->Pitch,
@@ -175,17 +210,58 @@ int DrvUtil_Video_WriteLFB(tDrvUtil_Video_BufInfo *FBInfo, size_t Offset, size_t
                        return 0;
                }
                
-               //TODO: Handle non 32-bpp framebuffer modes
-               if( FBInfo->Depth != 32 ) {
-                       Log_Warning("DrvUtil", "DrvUtil_Video_WriteLFB - Don't support non 32-bpp FB mode");
-                       return 0;
-               }       
+               switch(FBInfo->Depth)
+               {
+               case 15:
+               case 16:
+                       Log_Warning("DrvUtil", "TODO: Support 15/16 bpp modes in LFB write");
+                       break;
+               case 24:
+                       x = Offset % FBInfo->Width;
+                       y = Offset / FBInfo->Width;
+                       dest = (Uint8*)FBInfo->Framebuffer + y*FBInfo->Pitch;
+                       for( ; Length >= 4; Length -= 4 )
+                       {
+                               dest[x*3+0] = *src & 0xFF;
+                               dest[x*3+1] = (*src >> 8) & 0xFF;
+                               dest[x*3+2] = (*src >> 16) & 0xFF;
+                               x ++;
+                               if(x == FBInfo->Width) {
+                                       dest += FBInfo->Pitch;
+                                       x = 0;
+                               }
+                       }
+                       break;
+               case 32:
+                       // Copy to Frambuffer
+                       if( FBInfo->Pitch != FBInfo->Width*4 )
+                       {
+                               Uint32  *px;
+                               // Pitch isn't 4*Width
+                               x = Offset % FBInfo->Width;
+                               y = Offset / FBInfo->Height;
+                               
+                               px = (Uint32*)FBInfo->Framebuffer + y*FBInfo->Pitch/4;
 
-               
-               //TODO: Handle pitch != Width*BytesPerPixel
-               // Copy to Frambuffer
-               dest = (Uint8 *)FBInfo->Framebuffer + Offset;
-               memcpy(dest, Buffer, Length);
+                               for( ; Length >= 4; Length -= 4, x )
+                               {
+                                       px[x++] = *src ++;
+                                       if( x == FBInfo->Width ) {
+                                               x = 0;
+                                               px += FBInfo->Pitch;
+                                       }
+                               }
+                       }
+                       else
+                       {
+                               dest = (Uint8 *)FBInfo->Framebuffer + Offset;
+                               memcpy(dest, Buffer, Length);
+                       }
+                       break;
+               default:
+                       Log_Warning("DrvUtil", "DrvUtil_Video_WriteLFB - Unknown bit depthn %i", FBInfo->Depth);
+                       break;
+               }
                break;
        
        case VIDEO_BUFFMT_2DSTREAM:
@@ -199,11 +275,14 @@ int DrvUtil_Video_WriteLFB(tDrvUtil_Video_BufInfo *FBInfo, size_t Offset, size_t
                LEAVE('i', -1);
                return -1;
        }
+
+       DrvUtil_Video_DrawCursor(FBInfo, csr_x, csr_y);
+
        LEAVE('x', Length);
        return Length;
 }
 
-void DrvUtil_Video_SetCursor(tDrvUtil_Video_BufInfo *Buf, tVideo_IOCtl_Bitmap *Bitmap)
+int DrvUtil_Video_SetCursor(tDrvUtil_Video_BufInfo *Buf, tVideo_IOCtl_Bitmap *Bitmap)
 {
         int    csrX = Buf->CursorX, csrY = Buf->CursorY;
        size_t  size;
@@ -212,113 +291,200 @@ void DrvUtil_Video_SetCursor(tDrvUtil_Video_BufInfo *Buf, tVideo_IOCtl_Bitmap *B
        if( Buf->CursorBitmap )
        {
                DrvUtil_Video_RemoveCursor(Buf);
-               if( Bitmap->W != Buf->CursorBitmap->W || Bitmap->H != Buf->CursorBitmap->H )
+               if( !Bitmap || Bitmap->W != Buf->CursorBitmap->W || Bitmap->H != Buf->CursorBitmap->H )
                {
                        free( Buf->CursorSaveBuf );
                        Buf->CursorSaveBuf = NULL;
                }
-               free(Buf->CursorBitmap);
+               if( Buf->CursorBitmap != &gDrvUtil_TextModeCursor)
+                       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;
+       // If the new bitmap is null, disable drawing
+       if( !Bitmap )
+       {
+               Buf->CursorX = -1;
+               Buf->CursorY = -1;
+               return 0;
+       }
+
+       // Sanity check the bitmap
+       if( !CheckMem(Bitmap, sizeof(*Bitmap)) || !CheckMem(Bitmap->Data, Bitmap->W*Bitmap->H*sizeof(Uint32)) )
+       {
+               Log_Warning("DrvUtil", "DrvUtil_Video_SetCursor: Bitmap (%p) is in invalid memory", Bitmap);
+               errno = -EINVAL;
+               return -1;
+       }
+
+       // Don't take a copy of the DrvUtil provided cursor
+       if( Bitmap == &gDrvUtil_TextModeCursor )
+       {
+               Buf->CursorBitmap = Bitmap;
+       }
+       else
+       {
+               size = sizeof(tVideo_IOCtl_Bitmap) + Bitmap->W*Bitmap->H*4;
+               
+               // Take a copy
+               Buf->CursorBitmap = malloc( size );
+               memcpy(Buf->CursorBitmap, Bitmap, size);
        }
-       
-       // Take a copy
-       Buf->CursorBitmap = malloc( size );
-       memcpy(Buf->CursorBitmap, Bitmap, size);
        
        // Restore cursor position
        DrvUtil_Video_DrawCursor(Buf, csrX, csrY);
+       return 0;
 }
 
 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;
 
+       DrvUtil_Video_RemoveCursor(Buf);
+
+       // X < 0 disables the cursor
+       if( X < 0 ) {
+               Buf->CursorX = -1;
+               return ;
+       }
+
+       // Sanity checking
        if( X < 0 || Y < 0 )    return;
        if( X >= Buf->Width || Y >= Buf->Height )       return;
 
+       // Ensure the cursor is enabled
        if( !Buf->CursorBitmap )        return ;
+       
+       // Save cursor position (for changing the bitmap)
+       Buf->CursorX = X;       Buf->CursorY = Y;
 
+       // Apply cursor's center offset
        X -= Buf->CursorBitmap->XOfs;
        Y -= Buf->CursorBitmap->YOfs;
        
+       // Get the width of the cursor on screen (clipping to right/bottom edges)
        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;
-       }
+       // Clipp to left/top edges
+       if(X < 0) {     render_ox = -X; X = 0;  }
+       if(Y < 0) {     render_oy = -Y; Y = 0;  }
+
+       // Save values
+       Buf->CursorRenderW = render_w;  Buf->CursorRenderH = render_h;
+       Buf->CursorDestX   = X;         Buf->CursorDestY = Y;
+       Buf->CursorReadX   = render_ox; Buf->CursorReadY = render_oy;
 
-       save_pitch = Buf->CursorBitmap->W * bytes_per_px;       
+       // Call render routine
+       DrvUtil_Video_RenderCursor(Buf);
+}
+
+void DrvUtil_Video_RenderCursor(tDrvUtil_Video_BufInfo *Buf)
+{
+        int    src_x = Buf->CursorReadX, src_y = Buf->CursorReadY;
+        int    render_w = Buf->CursorRenderW, render_h = Buf->CursorRenderH;
+        int    dest_x = Buf->CursorDestX, dest_y = Buf->CursorDestY;
+        int    bytes_per_px = (Buf->Depth + 7) / 8;
+        int    save_pitch = Buf->CursorBitmap->W * bytes_per_px;
+       void    *dest;
+       Uint32  *src;
+        int    x, y;
 
-       dest = (void*)( (tVAddr)Buf->Framebuffer + Y * Buf->Pitch + X*bytes_per_px );
-       src = Buf->CursorBitmap->Data;
+       dest = (Uint8*)Buf->Framebuffer + dest_y*Buf->Pitch + dest_x*bytes_per_px;
+       src = Buf->CursorBitmap->Data + src_y * Buf->CursorBitmap->W + src_x;
+       
+       // Allocate save buffer if not already
        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 ++ )
+       for( y = 0; y < render_h; y ++ )
                memcpy(
                        (Uint8*)Buf->CursorSaveBuf + y*save_pitch,
-                       (Uint8*)dest + render_ox*bytes_per_px + y*Buf->Pitch,
+                       (Uint8*)dest + y*Buf->Pitch,
                        render_w*bytes_per_px
                        );
+
        // Draw the cursor
        switch(Buf->Depth)
        {
+       case 15:
+       case 16:
+               Log_Warning("DrvUtil", "TODO: Support 15/16 bpp modes in cursor draw");
+               break;
+       case 24:
+               for( y = 0; y < render_h; y ++ )
+               {
+                       Uint8   *px;
+                       px = dest;
+                       for(x = 0; x < render_w; x ++, px += 3)
+                       {
+                               Uint32  value = src[x];
+                               // TODO: Should I implement alpha blending?
+                               if(value & 0xFF000000)
+                               {
+                                       px[0] = value & 0xFF;
+                                       px[1] = (value >> 8) & 0xFF;
+                                       px[2] = (value >> 16) & 0xFF;
+                               }
+                               else
+                                       ;
+                       }
+                       src += Buf->CursorBitmap->W;
+                       dest = (Uint8*)dest + Buf->Pitch;
+               }
+               break;
        case 32:
-               src += render_oy * Buf->CursorBitmap->W;
-               for( y = render_oy; y < render_h; y ++ )
+               for( y = 0; y < render_h; y ++ )
                {
-                       int x;
-                       for(x = render_ox; x < render_w; x ++ )
+                       Uint32  *px;
+                       px = dest;
+                       for(x = 0; x < render_w; x ++, px ++)
                        {
-                               if(src[x] & 0xFF000000)
-                                       dest[x] = src[x];
+                               Uint32  value = src[x];
+                               // TODO: Should I implement alpha blending?
+                               if(value & 0xFF000000)
+                                       *px = value;
                                else
                                        ;       // NOP, completely transparent
                        }
                        src += Buf->CursorBitmap->W;
-                       dest = (void*)((Uint8*)dest + Buf->Pitch);
+                       dest = (Uint8*)dest + Buf->Pitch;
                }
                break;
        default:
-               Log_Error("DrvUtil", "TODO: Implement non 32-bpp cursor");
+               Log_Error("DrvUtil", "RenderCursor - Unknown bit depth %i", Buf->Depth);
+               Buf->CursorX = -1;
                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;
+       Uint8   *dest, *src;
 
+       // Just a little sanity
        if( !Buf->CursorBitmap || Buf->CursorX == -1 )  return ;
+       if( !Buf->CursorSaveBuf )       return ;
 
-       if( !Buf->CursorSaveBuf )
-               return ;
+//     Debug("DrvUtil_Video_RemoveCursor: (Buf=%p) dest_x=%i, dest_y=%i", Buf, Buf->CursorDestX, Buf->CursorDestY);
 
+       // Set up
        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);
+       dest = (Uint8*)Buf->Framebuffer + Buf->CursorDestY * Buf->Pitch + Buf->CursorDestX*bytes_per_px;
+       src = Buf->CursorSaveBuf;
        
+       // Copy each line back
+       for( y = 0; y < Buf->CursorRenderH; y ++ )
+       {
+               memcpy( dest, src, Buf->CursorRenderW * bytes_per_px );
+               src += save_pitch;
+               dest += Buf->Pitch;
+       }
+       
+       // Set the cursor as removed
        Buf->CursorX = -1;
 }
 
@@ -373,6 +539,9 @@ void DrvUtil_Video_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uin
                        }
                }
        }
+       else if(W == FBInfo->Width && FBInfo->Pitch == FBInfo->Width*bytes_per_px) {
+               memmove((Uint8*)FBInfo->Framebuffer + dst, (Uint8*)FBInfo->Framebuffer + src, H*FBInfo->Pitch);
+       }
        else {
                // Normal copy is OK
                while( H -- ) {
@@ -387,7 +556,7 @@ void DrvUtil_Video_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uin
 
 // --- Disk Driver Helpers ---
 Uint64 DrvUtil_ReadBlock(Uint64 Start, Uint64 Length, void *Buffer,
-       tDrvUtil_Callback ReadBlocks, Uint64 BlockSize, Uint Argument)
+       tDrvUtil_Read_Callback ReadBlocks, Uint64 BlockSize, Uint Argument)
 {
        Uint8   tmp[BlockSize]; // C99
        Uint64  block = Start / BlockSize;
@@ -456,8 +625,8 @@ Uint64 DrvUtil_ReadBlock(Uint64 Start, Uint64 Length, void *Buffer,
        return Length;
 }
 
-Uint64 DrvUtil_WriteBlock(Uint64 Start, Uint64 Length, void *Buffer,
-       tDrvUtil_Callback ReadBlocks, tDrvUtil_Callback WriteBlocks,
+Uint64 DrvUtil_WriteBlock(Uint64 Start, Uint64 Length, const void *Buffer,
+       tDrvUtil_Read_Callback ReadBlocks, tDrvUtil_Write_Callback WriteBlocks,
        Uint64 BlockSize, Uint Argument)
 {
        Uint8   tmp[BlockSize]; // C99

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