BuildConf/host - Slight fix to allow scan-build for non 64-bit architectures
[tpg/acess2.git] / Kernel / drvutil.c
index 00bfb78..00ab5ce 100644 (file)
@@ -28,6 +28,28 @@ 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 ---
@@ -109,17 +131,26 @@ int DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length,
 int DrvUtil_Video_WriteLFB(tDrvUtil_Video_BufInfo *FBInfo, size_t Offset, size_t Length, void *Buffer)
 {
        Uint8   *dest;
+       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;
                 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);
@@ -179,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:
@@ -203,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;
@@ -221,7 +296,8 @@ void DrvUtil_Video_SetCursor(tDrvUtil_Video_BufInfo *Buf, tVideo_IOCtl_Bitmap *B
                        free( Buf->CursorSaveBuf );
                        Buf->CursorSaveBuf = NULL;
                }
-               free(Buf->CursorBitmap);
+               if( Buf->CursorBitmap != &gDrvUtil_TextModeCursor)
+                       free(Buf->CursorBitmap);
                Buf->CursorBitmap = NULL;
        }
        
@@ -230,31 +306,45 @@ void DrvUtil_Video_SetCursor(tDrvUtil_Video_BufInfo *Buf, tVideo_IOCtl_Bitmap *B
        {
                Buf->CursorX = -1;
                Buf->CursorY = -1;
-               return ;
+               return 0;
        }
 
-       // Check the new bitmap is valid
-       size = sizeof(tVideo_IOCtl_Bitmap) + Bitmap->W*Bitmap->H*4;
-       if( !CheckMem(Bitmap, size) ) {
+       // 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);
-               return;
+               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    render_ox=0, render_oy=0, render_w, render_h;
 
+       DrvUtil_Video_RemoveCursor(Buf);
+
        // X < 0 disables the cursor
        if( X < 0 ) {
-               Render->CursorX = -1;
+               Buf->CursorX = -1;
                return ;
        }
 
@@ -314,17 +404,47 @@ void DrvUtil_Video_RenderCursor(tDrvUtil_Video_BufInfo *Buf)
                        (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:
                for( y = 0; y < render_h; y ++ )
                {
-                       for(x = 0; x < render_w; x ++ )
+                       Uint32  *px;
+                       px = dest;
+                       for(x = 0; x < render_w; x ++, px ++)
                        {
+                               Uint32  value = src[x];
                                // TODO: Should I implement alpha blending?
-                               if(src[x] & 0xFF000000)
-                                       ((Uint32*)dest)[x] = src[x];
+                               if(value & 0xFF000000)
+                                       *px = value;
                                else
                                        ;       // NOP, completely transparent
                        }
@@ -333,7 +453,8 @@ void DrvUtil_Video_RenderCursor(tDrvUtil_Video_BufInfo *Buf)
                }
                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;
        }
 }
@@ -348,6 +469,8 @@ void DrvUtil_Video_RemoveCursor(tDrvUtil_Video_BufInfo *Buf)
        if( !Buf->CursorBitmap || Buf->CursorX == -1 )  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 = (Uint8*)Buf->Framebuffer + Buf->CursorDestY * Buf->Pitch + Buf->CursorDestX*bytes_per_px;
@@ -416,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 -- ) {

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