X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Fdrvutil.c;h=41df6046358283abb847f2551c8dae2b3d72478c;hb=504e0f27f9240f083cefdc9f8dd7fefe0af544cc;hp=3835f0ceb08fd53bea50101d6d748f86587aba34;hpb=721e4b481a301692d40f231aa18dd247b6675a92;p=tpg%2Facess2.git diff --git a/Kernel/drvutil.c b/Kernel/drvutil.c index 3835f0ce..41df6046 100644 --- a/Kernel/drvutil.c +++ b/Kernel/drvutil.c @@ -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 @@ -12,6 +15,10 @@ // === 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,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 --- @@ -99,25 +128,38 @@ int DrvUtil_Video_2DStream(void *Ent, void *Buffer, int Length, return 0; } -int DrvUtil_Video_WriteLFB(int Mode, 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, void *Buffer) { Uint8 *dest; - ENTER("iMode pFBInfo xOffset xLength pBuffer", + 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); - switch( Mode ) + + 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 / 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); + Length /= sizeof(tVT_Char); Offset /= sizeof(tVT_Char); x = Offset % widthInChars; y = Offset / widthInChars; - + LOG("x = %i, y = %i", x, y); + // Sanity Check if(Offset > heightInChars * widthInChars) LEAVE_RET('i', 0); if(y >= heightInChars) LEAVE_RET('i', 0); @@ -128,7 +170,9 @@ int DrvUtil_Video_WriteLFB(int Mode, tDrvUtil_Video_BufInfo *FBInfo, size_t Offs } dest = FBInfo->Framebuffer; + LOG("dest = %p", dest); dest += y * giVT_CharHeight * FBInfo->Pitch; + LOG("dest = %p", dest); for( i = 0; i < Length; i++ ) { @@ -137,7 +181,7 @@ int DrvUtil_Video_WriteLFB(int Mode, tDrvUtil_Video_BufInfo *FBInfo, size_t Offs Log_Notice("DrvUtil", "Stopped at %i", i); break; } - + VT_Font_Render( chars->Ch, dest + x*giVT_CharWidth*bytes_per_px, FBInfo->Depth, FBInfo->Pitch, @@ -152,6 +196,7 @@ int DrvUtil_Video_WriteLFB(int Mode, tDrvUtil_Video_BufInfo *FBInfo, size_t Offs x = 0; y ++; dest += FBInfo->Pitch*giVT_CharHeight; + LOG("dest = %p", dest); } } Length = i * sizeof(tVT_Char); @@ -165,17 +210,57 @@ int DrvUtil_Video_WriteLFB(int Mode, tDrvUtil_Video_BufInfo *FBInfo, size_t Offs 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 ) + { + // Pitch isn't 4*Width + x = Offset % FBInfo->Width; + y = Offset / FBInfo->Height; + + dest = (Uint8*)FBInfo->Framebuffer + y*FBInfo->Pitch; - - //TODO: Handle pitch != Width*BytesPerPixel - // Copy to Frambuffer - dest = (Uint8 *)FBInfo->Framebuffer + Offset; - memcpy(dest, Buffer, Length); + for( ; Length >= 4; Length -= 4, x ) + { + ((Uint32*)dest)[x++] = *src ++; + if( x == FBInfo->Width ) { + x = 0; + dest += 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: @@ -189,10 +274,219 @@ int DrvUtil_Video_WriteLFB(int Mode, tDrvUtil_Video_BufInfo *FBInfo, size_t Offs LEAVE('i', -1); return -1; } + + DrvUtil_Video_DrawCursor(FBInfo, csr_x, csr_y); + LEAVE('x', Length); return Length; } +int 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 || Bitmap->W != Buf->CursorBitmap->W || Bitmap->H != Buf->CursorBitmap->H ) + { + free( Buf->CursorSaveBuf ); + Buf->CursorSaveBuf = NULL; + } + if( Buf->CursorBitmap != &gDrvUtil_TextModeCursor) + free(Buf->CursorBitmap); + Buf->CursorBitmap = NULL; + } + + // 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); + } + + // 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 ) { + 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; + + // 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; + + // 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 = (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 = 0; y < render_h; y ++ ) + memcpy( + (Uint8*)Buf->CursorSaveBuf + y*save_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: + for( y = 0; y < render_h; y ++ ) + { + Uint32 *px; + px = dest; + for(x = 0; x < render_w; x ++, px ++) + { + Uint32 value = src[x]; + // TODO: Should I implement alpha blending? + if(value & 0xFF000000) + *px = value; + else + ; // NOP, completely transparent + } + src += Buf->CursorBitmap->W; + dest = (Uint8*)dest + Buf->Pitch; + } + break; + default: + Log_Error("DrvUtil", "RenderCursor - Unknown bit depth %i", Buf->Depth); + Buf->CursorX = -1; + break; + } +} + +void DrvUtil_Video_RemoveCursor(tDrvUtil_Video_BufInfo *Buf) +{ + int bytes_per_px = (Buf->Depth + 7) / 8; + int y, save_pitch; + Uint8 *dest, *src; + + // Just a little sanity + 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; + 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; +} + void DrvUtil_Video_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour) { tDrvUtil_Video_BufInfo *FBInfo = Ent;