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

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