#include <stdio.h>
#include <video.h>
#include <wm.h>
+#include <string.h>
// === PROTOTYPES ===
void Video_Setup(void);
void Video_SetCursorPos(short X, short Y);
void Video_Update(void);
-void Video_FillRect(short X, short Y, short W, short H, uint32_t Color);
-void Video_DrawRect(short X, short Y, short W, short H, uint32_t Color);
+void Video_FillRect(int X, int Y, int W, int H, uint32_t Color);
// === GLOBALS ===
int giVideo_CursorX;
int giVideo_CursorY;
uint32_t *gpScreenBuffer;
+ int giVideo_FirstDirtyLine;
+ int giVideo_LastDirtyLine;
// === CODE ===
void Video_Setup(void)
exit(-1);
}
- // Set width
- tmpInt = giScreenWidth;
- tmpInt = ioctl( giTerminalFD, TERM_IOCTL_WIDTH, &tmpInt );
- if(tmpInt != giScreenWidth)
- {
- fprintf(stderr, "Warning: Selected width (%i) is invalid, clipped to %i\n",
- giScreenWidth, tmpInt);
- giScreenWidth = tmpInt;
- }
-
- // Set height
- tmpInt = giScreenHeight;
- tmpInt = ioctl( giTerminalFD, TERM_IOCTL_HEIGHT, &tmpInt );
- if(tmpInt != giScreenHeight)
- {
- fprintf(stderr, "Warning: Selected height (%i) is invalid, clipped to %i\n",
- giScreenHeight, tmpInt);
- giScreenHeight = tmpInt;
- }
// Set mode to video
tmpInt = TERM_MODE_FB;
ioctl( giTerminalFD, TERM_IOCTL_MODETYPE, &tmpInt );
+ // Get dimensions
+ giScreenWidth = ioctl( giTerminalFD, TERM_IOCTL_WIDTH, NULL );
+ giScreenHeight = ioctl( giTerminalFD, TERM_IOCTL_HEIGHT, NULL );
+
+ giVideo_LastDirtyLine = giScreenHeight;
+
// Force VT to be shown
ioctl( giTerminalFD, TERM_IOCTL_FORCESHOW, NULL );
void Video_Update(void)
{
- _SysDebug("Video_Update - gpScreenBuffer[0] = 0x%x", gpScreenBuffer[0]);
- seek(giTerminalFD, 0, 1);
- write(giTerminalFD, gpScreenBuffer, giScreenWidth*giScreenHeight*4);
+ int ofs = giVideo_FirstDirtyLine*giScreenWidth;
+ int size = (giVideo_LastDirtyLine-giVideo_FirstDirtyLine)*giScreenWidth;
+
+ if( giVideo_LastDirtyLine == 0 ) return;
+
+ _SysDebug("Video_Update - Updating lines %i to %i (0x%x+0x%x px)",
+ giVideo_FirstDirtyLine, giVideo_LastDirtyLine, ofs, size);
+ seek(giTerminalFD, ofs*4, 1);
+ write(giTerminalFD, gpScreenBuffer+ofs, size*4);
_SysDebug("Video_Update - Done");
+ giVideo_FirstDirtyLine = 0;
+ giVideo_LastDirtyLine = 0;
}
void Video_SetCursorPos(short X, short Y)
ioctl(giTerminalFD, TERM_IOCTL_GETSETCURSOR, &pos);
}
+void Video_FillRect(int X, int Y, int W, int H, uint32_t Colour)
+{
+ uint32_t *dest;
+ int i;
+
+ if(X < 0 || Y < 0) return;
+ if(W >= giScreenWidth) return;
+ if(H >= giScreenHeight) return;
+ if(X + W >= giScreenWidth) W = giScreenWidth - W;
+ if(Y + H >= giScreenHeight) W = giScreenHeight - H;
+
+ dest = gpScreenBuffer + Y * giScreenWidth + X;
+ while(H --)
+ {
+ for( i = W; i --; dest ++ ) *dest = Colour;
+ dest += giScreenWidth - W;
+ }
+}
+
/**
* \brief Blit an entire buffer to the screen
* \note Assumes Pitch = 4*W
*/
void Video_Blit(uint32_t *Source, short DstX, short DstY, short W, short H)
{
- int i;
uint32_t *buf;
-// _SysDebug("Video_Blit: (%p (%i, %i) %ix%i)", Source, DstX, DstY, W, H);
-
if( DstX >= giScreenWidth) return ;
if( DstY >= giScreenHeight) return ;
// TODO: Handle -ve X/Y by clipping
H = giScreenWidth - DstY;
if( W <= 0 || H <= 0 ) return;
+
+ if( DstX < giVideo_FirstDirtyLine )
+ giVideo_FirstDirtyLine = DstY;
+ if( DstY + H > giVideo_LastDirtyLine )
+ giVideo_LastDirtyLine = DstY + H;
-// _SysDebug(" Clipped to (%i, %i) %ix%i", DstX, DstY, W, H);
-// _SysDebug(" Source[0] = 0x%x", Source[0]);
buf = gpScreenBuffer + DstY*giScreenWidth + DstX;
- while( H -- )
+ if(W != giScreenWidth)
+ {
+ while( H -- )
+ {
+ memcpy(buf, Source, W*4);
+ Source += W;
+ buf += giScreenWidth;
+ }
+ }
+ else
{
- for( i = W; i --; )
- *buf++ = *Source++;
- buf += giScreenWidth - W;
+ memcpy(buf, Source, giScreenWidth*H*4);
}
}