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

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