📄 framebuffer.c
字号:
}
// Directly access memory instead of call putpixel function
// to make more effective performance of drawing a line
startOffset = y * LINE_SIZE + x1 * PIXEL_SIZE;
#ifdef DEBUG
printf("DEBUG_INFO: x1 = %d, x2 = %d, y = %d, startOffset = 0x%x\n", x1, x2, y, startOffset);
#endif
currPoint = frame_base + startOffset;
for (x = x1; x <= x2; x++)
{
switch (BPP)
{
case 8:
*(ByteType *)currPoint = _COLOR24_16(color) & 0xff;
break;
case 16:
*(WordType *)currPoint = _COLOR24_16(color) & 0xffff;
break;
}
currPoint += PIXEL_SIZE;
}
return;
}
// Draw a vertical line on the screen
void fb_DrawLine_V(int x, int y1, int y2, ColorType color/*, int xorm */)
{
short currLine;
void * currPoint;
y1 = (y1 < fb_clip.clipmin_y) ? fb_clip.clipmin_y : y1;
y2 = (y2 < fb_clip.clipmin_y) ? fb_clip.clipmin_y : y2;
y1 = (y1 > fb_clip.clipmax_y) ? fb_clip.clipmax_y : y1;
y2 = (y2 > fb_clip.clipmax_y) ? fb_clip.clipmax_y : y2;
if (x < fb_clip.clipmin_x || x > fb_clip.clipmax_x)
{
#ifdef ERR_DEBUG
printf("DEBUG_INFO: Pixel out of screen range.\n");
printf("DEBUG_INFO: x = %d, y1 = %d, y2 = %d\n", x, y1, y2);
#endif
return;
}
if (y1 > y2)
{
short tmp;
tmp = y1;
y1 = y2;
y2 = tmp;
}
// Directly access memory instead of call putpixel function
// to make more effective performance of drawing a line
currPoint = (ByteType *)frame_base + y1 * LINE_SIZE + x * PIXEL_SIZE;
#ifdef DEBUG
printf("DEBUG_INFO: x = %d, y1 = %d, y2 = %d, currPoint = 0x%x\n", x, y1, y2, currPoint);
#endif
for (currLine = y1; currLine <= y2; currLine++)
{
switch (BPP)
{
case 8:
*((ByteType *)currPoint) = (_COLOR24_8(color) & 0xff);
break;
case 16:
*((WordType *)currPoint) = (_COLOR24_16(color) & 0xffff);
break;
}
// Make a LINE_SIZE increment to the currPoint,
// in order to move point to the start position of next line
(ByteType *)currPoint += LINE_SIZE;
}
return;
}
// Draw a rectangle frame on the screen
void fb_DrawRect(int x1, int y1, int x2, int y2, ColorType color)
{
if (x1 > x2)
{
short tmp;
tmp = x1;
x1 = x2;
x2 = tmp;
}
if (y1 > y2)
{
short tmp;
tmp = y1;
y1 = y2;
y2 = tmp;
}
// Draw horitontal frame
fb_DrawLine_H(x1, x2, y1, color);
fb_DrawLine_H(x1, x2, y2, color);
// Draw vertical frame
fb_DrawLine_V(x1, y1 + 1, y2 - 1, color);
fb_DrawLine_V(x2, y1 + 1, y2 - 1, color);
return;
}
// Draw a rectangle frame on the screen
void fb_FillRect(int x1, int y1, int x2, int y2, ColorType color)
{
short currLine;
unsigned long startOffset;
void * currPoint;
int x;
if (x1 < fb_clip.clipmin_x || x1 > fb_clip.clipmax_x ||
x2 < fb_clip.clipmin_x || x2 > fb_clip.clipmax_x ||
y1 < fb_clip.clipmin_y || y1 > fb_clip.clipmax_y ||
y2 < fb_clip.clipmin_y || y2 > fb_clip.clipmax_y)
{
#ifdef ERR_DEBUG
printf("DEBUG_INFO: Pixel out of screen range.\n");
printf("DEBUG_INFO: x1 = %d, y1 = %d, x2 = %d, y2 = %d\n", x1, y1, x2, y2);
#endif
x1 = (x1 < fb_clip.clipmin_x) ? fb_clip.clipmin_x : x1;
x2 = (x2 < fb_clip.clipmin_x) ? fb_clip.clipmin_x : x2;
y1 = (y1 < fb_clip.clipmin_y) ? fb_clip.clipmin_y : y1;
y2 = (y2 < fb_clip.clipmin_y) ? fb_clip.clipmin_y : y2;
x1 = (x1 > fb_clip.clipmax_x) ? fb_clip.clipmax_x : x1;
x2 = (x2 > fb_clip.clipmax_x) ? fb_clip.clipmax_x : x2;
y1 = (y1 > fb_clip.clipmax_y) ? fb_clip.clipmax_y : y1;
y2 = (y2 > fb_clip.clipmax_y) ? fb_clip.clipmax_y : y2;
}
if (x1 > x2)
{
short tmp;
tmp = x1;
x1 = x2;
x2 = tmp;
}
if (y1 > y2)
{
short tmp;
tmp = y1;
y1 = y2;
y2 = tmp;
}
startOffset = y1 * LINE_SIZE + x1 * PIXEL_SIZE;
#ifdef DEBUG
printf("DEBUG_INFO: x1 = %d, y1 = %d, x2 = %d, y2= %d, color = 0x%x\n", x1, y1, x2, y2, color);
#endif
// Directly access memory instead of call putpixel function
// to make more effective performance of drawing a line
for (currLine = y1; currLine <= y2; currLine++)
{
currPoint = frame_base + startOffset;
for (x = x1; x <= x2; x++)
{
switch (BPP)
{
case 8:
*(ByteType *)currPoint = _COLOR24_16(color) & 0xff;
break;
case 16:
*(WordType *)currPoint = _COLOR24_16(color) & 0xffff;
break;
}
(ByteType *)currPoint += PIXEL_SIZE;
}
// Make a LINE_SIZE increment to the startOffset,
// in order to move point to the start position of next line
startOffset += SCREEN_WIDTH * PIXEL_SIZE;
}
return;
}
// Save screen content of specified range
void fb_SaveRange(int x1, int y1, int x2, int y2, ByteType * buffer, int * sw, int * sh)
{
short currLine;
unsigned long startOffset;
void * currPoint;
void * pBuf;
int x;
if (x1 < fb_clip.clipmin_x || x1 > fb_clip.clipmax_x ||
x2 < fb_clip.clipmin_x || x2 > fb_clip.clipmax_x ||
y1 < fb_clip.clipmin_y || y1 > fb_clip.clipmax_y ||
y2 < fb_clip.clipmin_y || y2 > fb_clip.clipmax_y)
{
#ifdef ERR_DEBUG
printf("DEBUG_INFO: Pixel out of screen range.\n");
printf("DEBUG_INFO: x1 = %d, y1 = %d, x2 = %d, y2 = %d\n", x1, y1, x2, y2);
#endif
x1 = (x1 < fb_clip.clipmin_x) ? fb_clip.clipmin_x : x1;
x2 = (x2 < fb_clip.clipmin_x) ? fb_clip.clipmin_x : x2;
y1 = (y1 < fb_clip.clipmin_y) ? fb_clip.clipmin_y : y1;
y2 = (y2 < fb_clip.clipmin_y) ? fb_clip.clipmin_y : y2;
x1 = (x1 > fb_clip.clipmax_x) ? fb_clip.clipmax_x : x1;
x2 = (x2 > fb_clip.clipmax_x) ? fb_clip.clipmax_x : x2;
y1 = (y1 > fb_clip.clipmax_y) ? fb_clip.clipmax_y : y1;
y2 = (y2 > fb_clip.clipmax_y) ? fb_clip.clipmax_y : y2;
}
if (x1 > x2)
{
short tmp;
tmp = x1;
x1 = x2;
x2 = tmp;
}
if (y1 > y2)
{
short tmp;
tmp = y1;
y1 = y2;
y2 = tmp;
}
startOffset = y1 * LINE_SIZE + x1 * PIXEL_SIZE;
if (buffer == NULL)
{
printf("buffer is NULL.\n");
return;
}
#ifdef DEBUG
printf("DEBUG_INFO: x1 = %d, y1 = %d, x2 = %d, y2= %d\n", x1, y1, x2, y2);
#endif
// Directly access memory instead of call putpixel function
// to make more effective performance of drawing a line
pBuf = buffer;
// printf("buffer = 0x%8x\n", buffer);
// printf("DEBUG_INFO: x1 = %d, y1 = %d, x2 = %d, y2= %d\n", x1, y1, x2, y2);
for (currLine = y1; currLine <= y2; currLine++)
{
// printf("currLine = %d\n", currLine);
currPoint = frame_base + startOffset;
// printf("pBuf = 0x%8x, currPoint = 0x%8x\n", pBuf, currPoint);
for (x = x1; x <= x2; x++)
{
switch (BPP)
{
case 8:
*(ByteType *)pBuf = *(ByteType *)currPoint;
break;
case 16:
*(WordType *)pBuf = *(WordType *)currPoint;
break;
}
(ByteType *)currPoint += PIXEL_SIZE;
(ByteType *)pBuf += PIXEL_SIZE;
}
// Make a LINE_SIZE increment to the startOffset,
// in order to move point to the start position of next line
startOffset += SCREEN_WIDTH * PIXEL_SIZE;
}
if (sw != NULL)
*sw = x2 - x1 + 1;
if (sh != NULL)
*sh = y2 - y1 + 1;
return;
}
// Load saved screen content to specified range
void fb_LoadRange(int x1, int y1, int x2, int y2, ByteType * buffer, int sw, int sh)
{
short currLine;
unsigned long startOffset;
void * linePointer;
void * currPoint;
void * pBuf;
int x;
int max_x, max_y;
if (x1 < fb_clip.clipmin_x || x1 > fb_clip.clipmax_x ||
x2 < fb_clip.clipmin_x || x2 > fb_clip.clipmax_x ||
y1 < fb_clip.clipmin_y || y1 > fb_clip.clipmax_y ||
y2 < fb_clip.clipmin_y || y2 > fb_clip.clipmax_y)
{
#ifdef ERR_DEBUG
printf("DEBUG_INFO: Pixel out of screen range.\n");
printf("DEBUG_INFO: x1 = %d, y1 = %d, x2 = %d, y2 = %d\n", x1, y1, x2, y2);
#endif
x1 = (x1 < fb_clip.clipmin_x) ? fb_clip.clipmin_x : x1;
x2 = (x2 < fb_clip.clipmin_x) ? fb_clip.clipmin_x : x2;
y1 = (y1 < fb_clip.clipmin_y) ? fb_clip.clipmin_y : y1;
y2 = (y2 < fb_clip.clipmin_y) ? fb_clip.clipmin_y : y2;
x1 = (x1 > fb_clip.clipmax_x) ? fb_clip.clipmax_x : x1;
x2 = (x2 > fb_clip.clipmax_x) ? fb_clip.clipmax_x : x2;
y1 = (y1 > fb_clip.clipmax_y) ? fb_clip.clipmax_y : y1;
y2 = (y2 > fb_clip.clipmax_y) ? fb_clip.clipmax_y : y2;
}
if (x1 > x2)
{
short tmp;
tmp = x1;
x1 = x2;
x2 = tmp;
}
if (y1 > y2)
{
short tmp;
tmp = y1;
y1 = y2;
y2 = tmp;
}
startOffset = y1 * LINE_SIZE + x1 * PIXEL_SIZE;
if (buffer == NULL)
{
printf("buffer is NULL.\n");
return;
}
#ifdef DEBUG
printf("DEBUG_INFO: x1 = %d, y1 = %d, x2 = %d, y2= %d\n", x1, y1, x2, y2);
#endif
max_x = x2 > (x1 + sw - 1) ? (x1 + sw - 1) : x2;
max_y = y2 > (y1 + sh - 1) ? (y1 + sh - 1) : y2;
// Directly access memory instead of call putpixel function
// to make more effective performance of drawing a line
linePointer = buffer;
pBuf = buffer;
// printf("buffer = 0x%8x\n", buffer);
// printf("max_x = %d, max_y = %d\n", max_x, max_y);
for (currLine = y1; currLine <= max_y; currLine++)
{
currPoint = frame_base + startOffset;
pBuf = linePointer;
for (x = x1; x <= max_x; x++)
{
switch (BPP)
{
case 8:
*(ByteType *)currPoint = *(ByteType *)pBuf;
break;
case 16:
*(WordType *)currPoint = *(WordType *)pBuf;
break;
}
(ByteType *)currPoint += PIXEL_SIZE;
(ByteType *)pBuf += PIXEL_SIZE;
}
// Make a LINE_SIZE increment to the startOffset,
// in order to move point to the start position of next line
startOffset += SCREEN_WIDTH * PIXEL_SIZE;
(ByteType *)linePointer += sw * PIXEL_SIZE;
}
return;
}
// GAL Interface functions
int InitFB(GFX * gfx)
{
if (strcmp(gfx->gfx_id, "FrameBuffer") != 0)
return -1;
fb_Init();
gfx->gfx_width = fb_GetScreenWidth();
gfx->gfx_height = fb_GetScreenHeight();
gfx->gfx_bpp = fb_GetScreenBpp();
gfx->gfx_colors = fb_GetScreenColors();
gfx->gfx_clip = &fb_clip;
gfx->putpixel = fb_PutPixel;
gfx->getpixel = fb_GetPixel;
gfx->drawvline = fb_DrawLine_V;
gfx->drawhline = fb_DrawLine_H;
gfx->drawrect = fb_DrawRect;
gfx->fillrect = fb_FillRect;
gfx->drawellipse = NULL;
gfx->fillellipse = NULL;
gfx->drawcircle = NULL;
gfx->fillcircle = NULL;
gfx->putchar = NULL;
gfx->putstr = NULL;
gfx->clearscreen = fb_Clear;
gfx->saverange = fb_SaveRange;
gfx->loadrange = fb_LoadRange;
return 0;
}
void ReleaseFB(GFX * gfx)
{
fb_Release();
}
#endif // __GAL_DRIVER_FB_C
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -