AcessNative - Updates for recent changes
[tpg/acess2.git] / AcessNative / acesskernel_src / video.c
1 /*
2  * Acess2 Native Kernel
3  * 
4  * Video Driver
5  */
6 #define VERSION ((0<<8)|10)
7 #define DEBUG   0
8 #include <acess.h>
9 #include <vfs.h>
10 #include <fs_devfs.h>
11 #include <modules.h>
12 #include <api_drv_video.h>
13 #include "ui.h"
14
15 // === PROTOTYPES ===
16  int    Video_Install(char **Arguments);
17 size_t  Video_Read(tVFS_Node *Node, Uint64 Offset, size_t Length, void *Buffer, Uint Flags);
18 size_t  Video_Write(tVFS_Node *Node, Uint64 Offset, size_t Length, const void *Buffer, Uint Flags);
19  int    Video_IOCtl(tVFS_Node *Node, int ID, void *Data);
20 // --- 2D Acceleration Functions --
21 void    Video_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour);
22 void    Video_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H);
23
24 // === GLOBALS ===
25 //MODULE_DEFINE(0, VERSION, NativeVideo, Video_Install, NULL, NULL);
26 tVFS_NodeType   gVideo_NodeType = {
27         .Read = Video_Read,
28         .Write = Video_Write,
29         .IOCtl = Video_IOCtl
30 };
31 tDevFS_Driver   gVideo_DriverStruct = {
32         NULL, "NativeVideo",
33         {.Type = &gVideo_NodeType}
34 };
35  int    giVideo_DriverID;
36  int    giVideo_CurrentFormat;
37 // --- 2D Video Stream Handlers ---
38 tDrvUtil_Video_2DHandlers       gVideo_2DFunctions = {
39         NULL,
40         Video_2D_Fill,
41         Video_2D_Blit
42 };
43
44 // === CODE ===
45 int Video_Install(char **Arguments)
46 {
47         // Install Device
48         giVideo_DriverID = DevFS_AddDevice( &gVideo_DriverStruct );
49         if(giVideo_DriverID == -1)
50                 return MODULE_ERR_MISC;
51         
52         return MODULE_ERR_OK;
53 }
54
55 /**
56  * \brief Read from framebuffer (unimplemented)
57  */
58 size_t Video_Read(tVFS_Node *Node, Uint64 Offset, size_t Length, void *Buffer, Uint Flags)
59 {
60         return 0;
61 }
62
63 /**
64  * \brief Write to the framebuffer
65  */
66 size_t Video_Write(tVFS_Node *Node, Uint64 Offset, size_t Length, const void *Buffer, Uint Flags)
67 {
68          int    i;
69         ENTER("pNode XOffset XLength pBuffer", Node, Offset, Length, Buffer);
70
71         if(Buffer == NULL) {
72                 LEAVE('i', 0);
73                 return 0;
74         }
75         // Text Mode
76         switch( giVideo_CurrentFormat )
77         {
78         case VIDEO_BUFFMT_TEXT:
79                 {
80                 const tVT_Char  *chars = Buffer;
81                 // int  pitch = giUI_Pitch;
82                  int    widthInChars = giUI_Width/giVT_CharWidth;
83                  int    heightInChars = giUI_Height/giVT_CharHeight;
84                  int    x, y;
85                 Uint32  tmpBuf[giVT_CharHeight*giVT_CharWidth];
86                 
87                 Length /= sizeof(tVT_Char);
88                 Offset /= sizeof(tVT_Char);
89                 
90                 x = Offset % widthInChars;
91                 y = Offset / widthInChars;
92                 
93                 // Sanity Check
94                 if( Offset > (Uint64)(heightInChars*widthInChars) ) {
95                         Log_Notice("Video", "Offset (%i) > %i*%i (%i)", Offset,
96                                 heightInChars, widthInChars, heightInChars*widthInChars);
97                         LEAVE('i', 0);
98                         return 0;
99                 }
100                 if(y >= heightInChars) {
101                         LEAVE('i', 0);
102                         return 0;
103                 }
104                 
105                 // Clip to screen size
106                 if( (int)Offset + (int)Length > heightInChars*widthInChars ) {
107                         Log_Debug("Video", "%i + %i > %i*%i (%i)",
108                                 (int)Offset, (int)Length, heightInChars, widthInChars, heightInChars*widthInChars);
109                         Length = heightInChars*widthInChars - Offset;
110                         Log_Notice("Video", "Clipping write size to %i characters", (int)Length);
111                 }
112                 
113 //              Log_Debug("Video", "(%i,%i) %i chars", x, y, (int)Length);
114                 
115                 // Print characters
116                 for( i = 0; i < (int)Length; i++ )
117                 {
118                         if( chars->Ch )
119                         {
120 //                              Log_Debug("Video", "Render Char 0x%x in 0x%03x:%03x",
121 //                                      chars->Ch, chars->FGCol, chars->BGCol);
122                                 memset(tmpBuf, 0xFF, giVT_CharWidth*giVT_CharHeight*4);
123                                 VT_Font_Render(
124                                         chars->Ch,
125                                         tmpBuf, 32, giVT_CharWidth*4,
126                                         VT_Colour12to24(chars->BGCol),
127                                         VT_Colour12to24(chars->FGCol)
128                                         );
129                                 UI_BlitBitmap(
130                                         x*giVT_CharWidth, y*giVT_CharHeight,
131                                         giVT_CharWidth, giVT_CharHeight,
132                                         tmpBuf
133                                         );
134                         }
135                         else
136                         {
137                                 UI_FillBitmap(
138                                         x*giVT_CharWidth, y*giVT_CharHeight,
139                                         giVT_CharWidth, giVT_CharHeight,
140                                         VT_Colour12to24(chars->BGCol)
141                                         );
142                         }
143                         
144                         chars ++;
145                         x ++;
146                         if( x >= widthInChars ) {
147                                 x = 0;
148                                 y ++;
149                                 //dest += pitch*giVT_CharHeight;
150                         }
151                 }
152                 Length *= sizeof(tVT_Char);
153                 }
154                 break;
155         
156         case VIDEO_BUFFMT_FRAMEBUFFER:
157                 {
158                  int    startX, startY;
159                 
160                 if(giUI_Pitch*giUI_Height < Offset+Length)
161                 {
162                         Log_Warning("Video", "Video_Write - Framebuffer Overflow");
163                         LEAVE('i', 0);
164                         return 0;
165                 }
166                 
167                 LOG("buffer = %p", Buffer);
168                 
169                 Offset /= 4;
170                 startX = Offset % giUI_Width;
171                 startY = Offset / giUI_Width;
172                 Length /= 4;
173
174                 if( startX + Length < giUI_Width )
175                 {
176                         // Single line
177                         UI_BlitBitmap(
178                                 startX, startY,
179                                 Length, 1,
180                                 Buffer);
181                 }
182                 else if( startX == 0 )
183                 {
184                         int     lines = Length / giUI_Width;
185                         int     rem = Length % giUI_Width;
186                         UI_BlitBitmap(0, startY, giUI_Width, lines, Buffer);
187                         if( rem ) {
188                                 UI_BlitBitmap(0, startY + lines, rem, 1, (Uint32*)Buffer + lines*giUI_Width);
189                         }
190                 }
191                 else
192                 {
193                         // First scanline (partial or full)
194                         UI_BlitBitmap(
195                                 startX, startY,
196                                 giUI_Width - startX, 1,
197                                 Buffer);
198                         
199                         Length -= giUI_Width - startX;
200                         Buffer += giUI_Width - startX;
201                         
202                         // Middle Scanlines
203                         for( i = 0; i < Length / giUI_Height; i ++ )
204                         {
205                                 UI_BlitBitmap(
206                                         0, startY + i,
207                                         giUI_Width, 1,
208                                         Buffer);
209                                 Buffer += giUI_Width;
210                         }
211                         
212                         // Final scanline (partial)
213                         if( Length % giUI_Height )
214                         {
215                                 UI_BlitBitmap(
216                                         0, startY + i,
217                                         Length % giUI_Height, 1,
218                                         Buffer);
219                         }
220                 }
221                 }
222                 break;
223         
224         case VIDEO_BUFFMT_2DSTREAM:
225                 Length = DrvUtil_Video_2DStream(
226                         NULL,   // Single framebuffer, so Ent is unused
227                         Buffer, Length, &gVideo_2DFunctions, sizeof(gVideo_2DFunctions)
228                         );
229                 break;
230         
231         default:
232                 LEAVE('i', -1);
233                 return -1;
234         }
235         
236         // Tell the UI to blit
237         UI_Redraw();
238         
239         LEAVE('X', Length);
240         return Length;
241 }
242
243 const char * csaVIDEO_IOCTLS[] = {DRV_IOCTLNAMES, DRV_VIDEO_IOCTLNAMES, NULL};
244 /**
245  * \brief Handle messages to the device
246  */
247 int Video_IOCtl(tVFS_Node *Node, int ID, void *Data)
248 {
249          int    ret;
250         tVideo_IOCtl_Mode       *mode = Data;
251         switch(ID)
252         {
253         BASE_IOCTLS(DRV_TYPE_VIDEO, "NativeVideo", VERSION, csaVIDEO_IOCTLS);
254         
255         // Video mode control
256         // - We cheat, and only have one mode
257         case VIDEO_IOCTL_GETSETMODE:
258                 return 0;
259         case VIDEO_IOCTL_FINDMODE:
260         case VIDEO_IOCTL_MODEINFO:
261                 mode->id = 0;
262                 mode->width = giUI_Width;
263                 mode->height = giUI_Height;
264                 mode->bpp = 32;
265                 mode->flags = 0;
266                 return 0;
267         
268         // Buffer mode
269         case VIDEO_IOCTL_SETBUFFORMAT:
270                 ret = giVideo_CurrentFormat;
271                 if(Data) {
272                         giVideo_CurrentFormat = *(int*)Data;
273                 }
274                 return ret;
275         
276         #if 0
277         case VIDEO_IOCTL_SETCURSOR:     // Set cursor position
278                 #if !BLINKING_CURSOR
279                 if(giVideo_CursorX > 0)
280                         Video_FlipCursor(Node);
281                 #endif
282                 giVideo_CursorX = ((tVideo_IOCtl_Pos*)Data)->x;
283                 giVideo_CursorY = ((tVideo_IOCtl_Pos*)Data)->y;
284                 if(     giVideo_CursorX < 0 || giVesaCursorY < 0
285                 ||      giVideo_CursorX >= gpVesaCurMode->width/giVT_CharWidth
286                 ||      giVideo_CursorY >= gpVesaCurMode->height/giVT_CharHeight)
287                 {
288                         #if BLINKING_CURSOR
289                         if(giVesaCursorTimer != -1) {
290                                 Time_RemoveTimer(giVesaCursorTimer);
291                                 giVesaCursorTimer = -1;
292                         }
293                         #endif
294                         giVesaCursorX = -1;
295                         giVesaCursorY = -1;
296                 }
297                 else {
298                         #if BLINKING_CURSOR
299                 //      Log_Debug("VESA", "Updating timer %i?", giVesaCursorTimer);
300                         if(giVesaCursorTimer == -1)
301                                 giVesaCursorTimer = Time_CreateTimer(VESA_CURSOR_PERIOD, Vesa_FlipCursor, Node);
302                         #else
303                         Vesa_FlipCursor(Node);
304                         #endif
305                 }
306                 //Log_Debug("VESA", "Cursor position (%i,%i) Timer %i", giVesaCursorX, giVesaCursorY, giVesaCursorTimer);
307                 return 0;
308         #endif
309         }
310         return 0;
311 }
312
313 // --- 2D Acceleration Functions --
314 void Video_2D_Fill(void *Ent, Uint16 X, Uint16 Y, Uint16 W, Uint16 H, Uint32 Colour)
315 {
316         UI_FillBitmap(X, Y, W, H, Colour);
317 }
318
319 void Video_2D_Blit(void *Ent, Uint16 DstX, Uint16 DstY, Uint16 SrcX, Uint16 SrcY, Uint16 W, Uint16 H)
320 {
321         UI_BlitFramebuffer(DstX, DstY, SrcX, SrcY, W, H);
322 }

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