fix a bug when using shadow engine and fbcon with double buffering enabled; fix a bug for bad size for destination line

This commit is contained in:
Vincent Wei
2023-07-10 22:52:28 +08:00
parent c60c19aad5
commit 872e299ad9
5 changed files with 206 additions and 91 deletions
+125 -59
View File
@@ -110,6 +110,88 @@ static void FB_WaitIdle(_THIS);
#define FBIO_ENABLE_CACHE 0x4631
#endif
#ifdef FBCON_DEBUG
static void print_vinfo(struct fb_var_screeninfo *vinfo)
{
fprintf(stderr, "Printing vinfo:\n");
fprintf(stderr, "txres: %d\n", vinfo->xres);
fprintf(stderr, "tyres: %d\n", vinfo->yres);
fprintf(stderr, "txres_virtual: %d\n", vinfo->xres_virtual);
fprintf(stderr, "tyres_virtual: %d\n", vinfo->yres_virtual);
fprintf(stderr, "txoffset: %d\n", vinfo->xoffset);
fprintf(stderr, "tyoffset: %d\n", vinfo->yoffset);
fprintf(stderr, "tbits_per_pixel: %d\n", vinfo->bits_per_pixel);
fprintf(stderr, "tgrayscale: %d\n", vinfo->grayscale);
fprintf(stderr, "tnonstd: %d\n", vinfo->nonstd);
fprintf(stderr, "tactivate: %d\n", vinfo->activate);
fprintf(stderr, "theight: %d\n", vinfo->height);
fprintf(stderr, "twidth: %d\n", vinfo->width);
fprintf(stderr, "taccel_flags: %d\n", vinfo->accel_flags);
fprintf(stderr, "tpixclock: %d\n", vinfo->pixclock);
fprintf(stderr, "tleft_margin: %d\n", vinfo->left_margin);
fprintf(stderr, "tright_margin: %d\n", vinfo->right_margin);
fprintf(stderr, "tupper_margin: %d\n", vinfo->upper_margin);
fprintf(stderr, "tlower_margin: %d\n", vinfo->lower_margin);
fprintf(stderr, "thsync_len: %d\n", vinfo->hsync_len);
fprintf(stderr, "tvsync_len: %d\n", vinfo->vsync_len);
fprintf(stderr, "tsync: %d\n", vinfo->sync);
fprintf(stderr, "tvmode: %d\n", vinfo->vmode);
fprintf(stderr, "tred: %d/%d\n", vinfo->red.length, vinfo->red.offset);
fprintf(stderr, "tgreen: %d/%d\n", vinfo->green.length, vinfo->green.offset);
fprintf(stderr, "tblue: %d/%d\n", vinfo->blue.length, vinfo->blue.offset);
fprintf(stderr, "talpha: %d/%d\n", vinfo->transp.length, vinfo->transp.offset);
}
static void print_finfo(struct fb_fix_screeninfo *finfo)
{
fprintf(stderr, "Printing finfo:\n");
fprintf(stderr, "tsmem_start = %p\n", (char *)finfo->smem_start);
fprintf(stderr, "tsmem_len = %d\n", finfo->smem_len);
fprintf(stderr, "ttype = %d\n", finfo->type);
fprintf(stderr, "ttype_aux = %d\n", finfo->type_aux);
fprintf(stderr, "tvisual = %d\n", finfo->visual);
fprintf(stderr, "txpanstep = %d\n", finfo->xpanstep);
fprintf(stderr, "typanstep = %d\n", finfo->ypanstep);
fprintf(stderr, "tywrapstep = %d\n", finfo->ywrapstep);
fprintf(stderr, "tline_length = %d\n", finfo->line_length);
fprintf(stderr, "tmmio_start = %p\n", (char *)finfo->mmio_start);
fprintf(stderr, "tmmio_len = %d\n", finfo->mmio_len);
fprintf(stderr, "taccel = %d\n", finfo->accel);
}
#endif /* FBCON_DEBUG */
static void FB_UpdateRectsPanning (_THIS, int numrects, GAL_Rect *rects)
{
(void)this;
(void)numrects;
(void)rects;
return;
}
static BOOL FB_SyncUpdatePanning (_THIS)
{
currt_vinfo.yoffset = this->hidden->idx_buffer * currt_vinfo.yres;
if (ioctl(console_fd, FBIOPAN_DISPLAY, &currt_vinfo) < 0) {
_WRN_PRINTF("Failed ioctl(): FBIOPAN_DISPLAY\n");
return FALSE;
}
int old = this->hidden->idx_buffer;
this->hidden->idx_buffer = 1 - this->hidden->idx_buffer;
memcpy(this->hidden->buffers[this->hidden->idx_buffer],
this->hidden->buffers[old], this->hidden->len_buffer);
int dummy = 0;
if (ioctl(console_fd, FBIO_WAITFORVSYNC, &dummy) < 0) {
_WRN_PRINTF("Failed ioctl(): FBIO_WAITFORVSYNC\n");
return FALSE;
}
this->hidden->real_screen->pixels =
this->hidden->buffers[this->hidden->idx_buffer];
return TRUE;
}
static BOOL FB_SyncUpdate (_THIS)
{
if (IsRectEmpty (&this->hidden->dirty_rc))
@@ -375,6 +457,12 @@ static int FB_VideoInit(_THIS, GAL_PixelFormat *vformat)
FB_VideoQuit(this);
return(-1);
}
#ifdef FBCON_DEBUG
fprintf (stderr, "Printing original finfo:\n");
print_finfo(&finfo);
#endif
switch (finfo.type) {
case FB_TYPE_PACKED_PIXELS:
/* Supported, no worries.. */
@@ -523,56 +611,6 @@ static GAL_Rect **FB_ListModes(_THIS, GAL_PixelFormat *format, Uint32 flags)
return (GAL_Rect**) -1;
}
#ifdef FBCON_DEBUG
static void print_vinfo(struct fb_var_screeninfo *vinfo)
{
fprintf(stderr, "Printing vinfo:\n");
fprintf(stderr, "txres: %d\n", vinfo->xres);
fprintf(stderr, "tyres: %d\n", vinfo->yres);
fprintf(stderr, "txres_virtual: %d\n", vinfo->xres_virtual);
fprintf(stderr, "tyres_virtual: %d\n", vinfo->yres_virtual);
fprintf(stderr, "txoffset: %d\n", vinfo->xoffset);
fprintf(stderr, "tyoffset: %d\n", vinfo->yoffset);
fprintf(stderr, "tbits_per_pixel: %d\n", vinfo->bits_per_pixel);
fprintf(stderr, "tgrayscale: %d\n", vinfo->grayscale);
fprintf(stderr, "tnonstd: %d\n", vinfo->nonstd);
fprintf(stderr, "tactivate: %d\n", vinfo->activate);
fprintf(stderr, "theight: %d\n", vinfo->height);
fprintf(stderr, "twidth: %d\n", vinfo->width);
fprintf(stderr, "taccel_flags: %d\n", vinfo->accel_flags);
fprintf(stderr, "tpixclock: %d\n", vinfo->pixclock);
fprintf(stderr, "tleft_margin: %d\n", vinfo->left_margin);
fprintf(stderr, "tright_margin: %d\n", vinfo->right_margin);
fprintf(stderr, "tupper_margin: %d\n", vinfo->upper_margin);
fprintf(stderr, "tlower_margin: %d\n", vinfo->lower_margin);
fprintf(stderr, "thsync_len: %d\n", vinfo->hsync_len);
fprintf(stderr, "tvsync_len: %d\n", vinfo->vsync_len);
fprintf(stderr, "tsync: %d\n", vinfo->sync);
fprintf(stderr, "tvmode: %d\n", vinfo->vmode);
fprintf(stderr, "tred: %d/%d\n", vinfo->red.length, vinfo->red.offset);
fprintf(stderr, "tgreen: %d/%d\n", vinfo->green.length, vinfo->green.offset);
fprintf(stderr, "tblue: %d/%d\n", vinfo->blue.length, vinfo->blue.offset);
fprintf(stderr, "talpha: %d/%d\n", vinfo->transp.length, vinfo->transp.offset);
}
static void print_finfo(struct fb_fix_screeninfo *finfo)
{
fprintf(stderr, "Printing finfo:\n");
fprintf(stderr, "tsmem_start = %p\n", (char *)finfo->smem_start);
fprintf(stderr, "tsmem_len = %d\n", finfo->smem_len);
fprintf(stderr, "ttype = %d\n", finfo->type);
fprintf(stderr, "ttype_aux = %d\n", finfo->type_aux);
fprintf(stderr, "tvisual = %d\n", finfo->visual);
fprintf(stderr, "txpanstep = %d\n", finfo->xpanstep);
fprintf(stderr, "typanstep = %d\n", finfo->ypanstep);
fprintf(stderr, "tywrapstep = %d\n", finfo->ywrapstep);
fprintf(stderr, "tline_length = %d\n", finfo->line_length);
fprintf(stderr, "tmmio_start = %p\n", (char *)finfo->mmio_start);
fprintf(stderr, "tmmio_len = %d\n", finfo->mmio_len);
fprintf(stderr, "taccel = %d\n", finfo->accel);
}
#endif /* FBCON_DEBUG */
static GAL_Surface *FB_SetVideoMode(_THIS, GAL_Surface *current,
int width, int height, int bpp, Uint32 flags)
{
@@ -605,6 +643,11 @@ static GAL_Surface *FB_SetVideoMode(_THIS, GAL_Surface *current,
FB_RestorePalette (this);
}
if (ioctl(console_fd, FBIOGET_FSCREENINFO, &finfo) < 0) {
GAL_SetError("NEWGAL>FBCON: Couldn't get console hardware info");
return(NULL);
}
/* Set the video mode and get the final screen format */
if (ioctl(console_fd, FBIOGET_VSCREENINFO, &vinfo) < 0) {
GAL_SetError("NEWGAL>FBCON: Couldn't get console screen info\n");
@@ -612,9 +655,6 @@ static GAL_Surface *FB_SetVideoMode(_THIS, GAL_Surface *current,
}
#ifdef FBCON_DEBUG
fprintf (stderr, "Printing original finfo:\n");
print_finfo(&finfo);
fprintf (stderr, "Printing original vinfo:\n");
print_vinfo(&vinfo);
#endif
@@ -663,7 +703,6 @@ static GAL_Surface *FB_SetVideoMode(_THIS, GAL_Surface *current,
vinfo.yres_virtual = maxheight;
}
}
cache_vinfo = vinfo;
#ifdef FBCON_DEBUG
fprintf (stderr, "NEWGAL>FBCON: Printing actual vinfo:\n");
print_vinfo(&vinfo);
@@ -724,6 +763,28 @@ static GAL_Surface *FB_SetVideoMode(_THIS, GAL_Surface *current,
current->pitch = finfo.line_length;
current->pixels = mapped_mem+mapped_offset;
/* Since 5.0.13, use FBIOPAN_DISPLAY if possible */
this->hidden->nr_buffers = finfo.smem_len / (vinfo.yres * current->pitch);
if (this->hidden->nr_buffers > 1) {
this->hidden->nr_buffers = 2;
vinfo.yres_virtual = this->hidden->nr_buffers * vinfo.yres;
if (ioctl(console_fd, FBIOPUT_VSCREENINFO, &vinfo) < 0) {
GAL_SetError("NEWGAL>FBCON: Couldn't enable virtual yres");
this->hidden->nr_buffers = 0;
}
else {
this->hidden->len_buffer = finfo.line_length * vinfo.yres;
this->hidden->buffers[0] = mapped_mem+mapped_offset;
this->hidden->buffers[1] = this->hidden->buffers[0] +
this->hidden->len_buffer;
this->hidden->idx_buffer = 1;
current->pixels = this->hidden->buffers[this->hidden->idx_buffer];
}
}
currt_vinfo = vinfo;
/* Set up the information for hardware surfaces */
surfaces_mem = (char *)current->pixels +
vinfo.yres_virtual*current->pitch;
@@ -764,12 +825,12 @@ static GAL_Surface *FB_SetVideoMode(_THIS, GAL_Surface *current,
sigma8654_hdmi_init();
#endif
// this is a trick in order that GAL_CreateRGBSurface tries to
// allocate hardware surface first.
GAL_PublicSurface = current;
#ifdef _MGSCHEMA_COMPOSITING
if (mgIsServer) {
// this is a trick in order that GAL_CreateRGBSurface tries to
// allocate hardware surface first.
GAL_PublicSurface = current;
dblbuff = TRUE;
}
else {
@@ -795,7 +856,7 @@ static GAL_Surface *FB_SetVideoMode(_THIS, GAL_Surface *current,
#endif
/* create shadow screen */
this->hidden->shadow_screen = GAL_CreateRGBSurface (GAL_HWSURFACE,
this->hidden->shadow_screen = GAL_CreateRGBSurface (GAL_SWSURFACE,
current->w, current->h,
current->format->BitsPerPixel,
current->format->Rmask, current->format->Gmask,
@@ -811,6 +872,7 @@ static GAL_Surface *FB_SetVideoMode(_THIS, GAL_Surface *current,
this->UpdateRects = shadowScreen_UpdateRects;
this->SyncUpdate = FB_SyncUpdate;
current->video = this;
this->hidden->real_screen = current;
current = this->hidden->shadow_screen;
@@ -827,6 +889,10 @@ static GAL_Surface *FB_SetVideoMode(_THIS, GAL_Surface *current,
else {
this->hidden->real_screen = current;
this->hidden->shadow_screen = NULL;
if (this->hidden->nr_buffers > 1) {
this->UpdateRects = FB_UpdateRectsPanning;
this->SyncUpdate = FB_SyncUpdatePanning;
}
}
/* We're done */
+8 -8
View File
@@ -90,11 +90,17 @@ struct GAL_PrivateVideoData {
/* end of header for shadow screen */
int console_fd;
struct fb_var_screeninfo cache_vinfo;
struct fb_var_screeninfo currt_vinfo;
struct fb_var_screeninfo saved_vinfo;
int saved_cmaplen;
__u16 *saved_cmap;
/* Since 5.0.13, use FBIOPAN_DISPLAY if possible */
int nr_buffers;
int idx_buffer;
unsigned len_buffer;
char *buffers[2];
#ifdef _MGHAVE_PCIACCESS
int pci_accel_driver;
#endif
@@ -115,13 +121,7 @@ struct GAL_PrivateVideoData {
/* Old variable names */
#define console_fd (this->hidden->console_fd)
#define current_vt (this->hidden->current_vt)
#define saved_vt (this->hidden->saved_vt)
#define keyboard_fd (this->hidden->keyboard_fd)
#define saved_kbd_mode (this->hidden->saved_kbd_mode)
#define saved_kbd_termios (this->hidden->saved_kbd_termios)
#define mouse_fd (this->hidden->mouse_fd)
#define cache_vinfo (this->hidden->cache_vinfo)
#define currt_vinfo (this->hidden->currt_vinfo)
#define saved_vinfo (this->hidden->saved_vinfo)
#define saved_cmaplen (this->hidden->saved_cmaplen)
#define saved_cmap (this->hidden->saved_cmap)
+65 -16
View File
@@ -160,11 +160,13 @@ static void refresh_ccw_32bpp(ShadowFBHeader* shadowfb_header,
dst_height = RECTH(dst_update);
BYTE line_pixels[dst_width * 4];
/* Copy the bits from Shadow FrameBuffer to console FrameBuffer */
/* Copy the bits from Shadow FrameBuffer to real FrameBuffer */
src_bits = (BYTE *)shadowfb_header + shadowfb_header->fb_offset;
src_bits += src_update.top * shadowfb_header->pitch + src_update.left * 4;
src_bits += src_update.top * shadowfb_header->pitch +
src_update.left * 4;
dst_line = (BYTE *)realfb_info->fb + (dst_update.bottom - 1) *
realfb_info->pitch;
dst_line = (BYTE *)realfb_info->fb + (dst_update.bottom - 1) * realfb_info->pitch;
for (x = 0; x < dst_height; x++) {
/* Copy the bits from vertical line to horizontal line */
const BYTE* ver_bits = src_bits;
@@ -176,12 +178,53 @@ static void refresh_ccw_32bpp(ShadowFBHeader* shadowfb_header,
hor_bits += 4;
}
memcpy(dst_line + (dst_update.left << 2), line_pixels, dst_width << 2);
memcpy(dst_line + (dst_update.left << 2), line_pixels,
dst_width << 2);
src_bits += 4;
dst_line -= realfb_info->pitch;
}
}
static void refresh_cw_32bpp(ShadowFBHeader* shadowfb_header,
RealFBInfo* realfb_info, void* update)
{
RECT src_update = *(RECT*)update;
RECT dst_update;
const BYTE *src_bits;
BYTE *dst_line;
int dst_width, dst_height;
int x, y;
_get_dst_rect_cw(&dst_update, &src_update, realfb_info);
dst_width = RECTW(dst_update);
dst_height = RECTH(dst_update);
BYTE line_pixels[dst_width * 4];
/* Copy the bits from Shadow FrameBuffer to real FrameBuffer */
src_bits = (BYTE *)shadowfb_header + shadowfb_header->fb_offset;
src_bits += (src_update.bottom - 1) * shadowfb_header->pitch +
src_update.left * 4;
dst_line = (BYTE *)realfb_info->fb + dst_update.top *
realfb_info->pitch;
for (x = 0; x < dst_height; x++) {
/* Copy the bits from vertical line to horizontal line */
const BYTE* ver_bits = src_bits;
BYTE* hor_bits = line_pixels;
for (y = 0; y < dst_width; y++) {
*(Uint32 *)hor_bits = *(Uint32 *)ver_bits;
ver_bits -= shadowfb_header->pitch;
hor_bits += 4;
}
memcpy(dst_line + (dst_update.left << 2), line_pixels,
dst_width << 2);
src_bits += 4;
dst_line += realfb_info->pitch;
}
}
#endif
extern void refresh_normal_msb_left (ShadowFBHeader * shadowfb_header, RealFBInfo *realfb_info, void* update);
@@ -382,13 +425,16 @@ static int RealEngine_GetInfo (RealFBInfo * realfb_info)
realfb_info->real_device = real_device;
real_device->VideoInit(realfb_info->real_device, &real_vformat);
real_device->screen = GAL_CreateRGBSurface (GAL_SWSURFACE,
GAL_Surface *prev_surf, *screen;
prev_surf = GAL_CreateRGBSurface (GAL_SWSURFACE,
0, 0, real_vformat.BitsPerPixel, real_vformat.Rmask,
real_vformat.Gmask, real_vformat.Bmask, real_vformat.Amask);
real_device->screen = NULL;
/* VW: SetVideoMode may return a new surface */
real_device->screen = real_device->SetVideoMode(realfb_info->real_device,
real_device->screen, w, h, depth, GAL_HWPALETTE);
screen = real_device->SetVideoMode(realfb_info->real_device,
prev_surf, w, h, depth, GAL_HWPALETTE);
real_device->screen = (screen != NULL) ? screen : prev_surf;
if (real_device->screen == NULL) {
_ERR_PRINTF ("NEWGAL>SHADOW: can't create screen of real engine.\n");
return -1;
@@ -539,11 +585,6 @@ static void schedule_updaters(_THIS, RECT *dirty_rc)
}
*/
/* wait for the finish of extra updaters */
for (i = 0; i < this->hidden->nr_updaters; i++) {
sem_wait(&this->hidden->sync_sem);
}
/* partition the dirty rectangle horizontally */
int span = h / (this->hidden->nr_updaters);
if (span == 0) {
@@ -585,6 +626,11 @@ static void schedule_updaters(_THIS, RECT *dirty_rc)
shadow_fb_ops.refresh(_shadowfbheader, this->hidden->realfb_info,
this->hidden->dirty_rcs + this->hidden->nr_updaters);
*/
/* wait for the finish of extra updaters */
for (i = 0; i < this->hidden->nr_updaters; i++) {
sem_wait(&this->hidden->sync_sem);
}
}
static BOOL SHADOW_SyncUpdateConcurrently (_THIS)
@@ -844,7 +890,7 @@ static GAL_Surface *SHADOW_SetVideoMode(_THIS, GAL_Surface *current,
ret = 0;
bzero(&shadowfbheader, sizeof(shadowfbheader));
realfb_info = malloc (sizeof(RealFBInfo));
realfb_info = calloc (1, sizeof(RealFBInfo));
if (shadow_fb_ops.get_realfb_info (realfb_info))
{
_ERR_PRINTF ("NEWGAL>SHADOW: "
@@ -991,9 +1037,12 @@ static GAL_Surface *SHADOW_SetVideoMode(_THIS, GAL_Surface *current,
}
}
#else
if (_shadowfbheader->depth == 32 &&
this->hidden->realfb_info->flags & _ROT_DIR_CCW)
shadow_fb_ops.refresh = refresh_ccw_32bpp;
if (_shadowfbheader->depth == 32) {
if (this->hidden->realfb_info->flags & _ROT_DIR_CCW)
shadow_fb_ops.refresh = refresh_ccw_32bpp;
else if (this->hidden->realfb_info->flags & _ROT_DIR_CW)
shadow_fb_ops.refresh = refresh_cw_32bpp;
}
#endif
/* We're done */
+4 -4
View File
@@ -230,7 +230,7 @@ void refresh_cw_msb_left (ShadowFBHeader *shadowfb_header, RealFBInfo *realfb_in
BYTE* dst_line;
int dst_width, dst_height;
int x, y;
BYTE line_pixels[shadowfb_header->pitch];
BYTE line_pixels[realfb_info->pitch];
_get_dst_rect_cw (&dst_update, &src_update, realfb_info);
@@ -332,7 +332,7 @@ void refresh_ccw_msb_left (ShadowFBHeader* shadowfb_header, RealFBInfo* realfb_i
BYTE* dst_line;
int dst_width, dst_height;
int x, y;
BYTE line_pixels[shadowfb_header->pitch];
BYTE line_pixels[realfb_info->pitch];
_get_dst_rect_ccw (&dst_update, &src_update, realfb_info);
@@ -433,7 +433,7 @@ void refresh_hflip_msb_left (ShadowFBHeader* shadowfb_header, RealFBInfo* realfb
BYTE* dst_line;
int src_width, src_height;
int x, y;
BYTE line_pixels[shadowfb_header->pitch];
BYTE line_pixels[realfb_info->pitch];
/* Round the update rectangle. */
round_rect(realfb_info->depth, &src_update);
@@ -527,7 +527,7 @@ void refresh_vflip_msb_left (ShadowFBHeader* shadowfb_header, RealFBInfo* realfb
BYTE* dst_line;
int src_width, src_height;
int x, y;
BYTE line_pixels[shadowfb_header->pitch];
BYTE line_pixels[realfb_info->pitch];
/* Round the update rectangle. */
round_rect (realfb_info->depth, &src_update);
+4 -4
View File
@@ -286,7 +286,7 @@ void refresh_cw_msb_right (ShadowFBHeader *shadowfb_header,
BYTE* dst_line;
int dst_width, dst_height;
int x, y;
BYTE line_pixels[shadowfb_header->pitch];
BYTE line_pixels[realfb_info->pitch];
_get_dst_rect_cw (&dst_update, &src_update, realfb_info);
@@ -387,7 +387,7 @@ void refresh_ccw_msb_right(ShadowFBHeader* shadowfb_header,
RECT dst_update;
const BYTE* src_bits;
BYTE* dst_line;
BYTE line_pixels[shadowfb_header->pitch];
BYTE line_pixels[realfb_info->pitch];
int dst_width, dst_height;
int x, y;
@@ -500,7 +500,7 @@ void refresh_hflip_msb_right (ShadowFBHeader* shadowfb_header, RealFBInfo* realf
BYTE* dst_line;
int src_width, src_height;
int x, y;
BYTE line_pixels[shadowfb_header->pitch];
BYTE line_pixels[realfb_info->pitch];
/* Round the update rectangle. */
round_rect(realfb_info->depth, &src_update);
@@ -603,7 +603,7 @@ void refresh_vflip_msb_right (ShadowFBHeader* shadowfb_header, RealFBInfo* realf
BYTE* dst_line;
int src_width, src_height;
int x, y;
BYTE line_pixels[shadowfb_header->pitch];
BYTE line_pixels[realfb_info->pitch];
/* Round the update rectangle. */
round_rect (realfb_info->depth, &src_update);