Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 68 additions & 4 deletions grub-core/video/fb/fbblit.c
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NOTE: grub_video_fb_dispatch_blit falls back to unoptimized blitters
when rotation is enabled. Optimized blitters currently do not
support transformed coordinates.

Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ grub_video_fbblit_replace (struct grub_video_fbblit_info *dst,
dst_color = grub_video_fb_map_rgba (src_red, src_green,
src_blue, src_alpha);

set_pixel (dst, x + i, y + j, dst_color);
set_pixel (dst, x + trans_x(i, j, dst->mode_info),
y + trans_y(i,j, dst->mode_info), dst_color);
}
}
}
Expand Down Expand Up @@ -1195,11 +1196,13 @@ grub_video_fbblit_blend (struct grub_video_fbblit_info *dst,
{
dst_color = grub_video_fb_map_rgba (src_red, src_green,
src_blue, src_alpha);
set_pixel (dst, x + i, y + j, dst_color);
set_pixel (dst, x + trans_x(i, j, dst->mode_info),
y + trans_y(i,j, dst->mode_info), dst_color);
continue;
}

dst_color = get_pixel (dst, x + i, y + j);
dst_color = get_pixel (dst, x + trans_x(i, j, dst->mode_info),
y + trans_y(i,j, dst->mode_info));

grub_video_fb_unmap_color_int (dst, dst_color, &dst_red,
&dst_green, &dst_blue, &dst_alpha);
Expand All @@ -1212,7 +1215,8 @@ grub_video_fbblit_blend (struct grub_video_fbblit_info *dst,
dst_color = grub_video_fb_map_rgba (dst_red, dst_green, dst_blue,
dst_alpha);

set_pixel (dst, x + i, y + j, dst_color);
set_pixel (dst, x + trans_x(i, j, dst->mode_info),
y + trans_y(i,j, dst->mode_info), dst_color);
}
}
}
Expand Down Expand Up @@ -1936,6 +1940,66 @@ grub_video_fb_dispatch_blit (struct grub_video_fbblit_info *target,
unsigned int width, unsigned int height,
int offset_x, int offset_y)
{
if (target->mode_info->rotation == GRUB_VIDEO_ROTATE_90)
{
int nx = y;
int ny = target->mode_info->width - x - 1;
if (oper == GRUB_VIDEO_BLIT_REPLACE)
{
/* No optimized replace operator found, use default (slow) blitter. */
grub_video_fbblit_replace(target, source, nx, ny, width, height,
offset_x, offset_y);
return;
}
else
{
/* No optimized replace operator found, use default (slow) blitter. */
grub_video_fbblit_blend(target, source, nx, ny, width, height,
offset_x, offset_y);
return;
}
}

if (target->mode_info->rotation == GRUB_VIDEO_ROTATE_180)
{
int nx = target->mode_info->width - x - 1;
int ny = target->mode_info->height - y - 1;
if (oper == GRUB_VIDEO_BLIT_REPLACE)
{
/* No optimized replace operator found, use default (slow) blitter. */
grub_video_fbblit_replace(target, source, nx, ny, width, height,
offset_x, offset_y);
return;
}
else
{
/* No optimized replace operator found, use default (slow) blitter. */
grub_video_fbblit_blend(target, source, nx, ny, width, height,
offset_x, offset_y);
return;
}
}

if (target->mode_info->rotation == GRUB_VIDEO_ROTATE_270)
{
int nx = target->mode_info->height - y - 1;
int ny = x;
if (oper == GRUB_VIDEO_BLIT_REPLACE)
{
/* No optimized replace operator found, use default (slow) blitter. */
grub_video_fbblit_replace(target, source, nx, ny, width, height,
offset_x, offset_y);
return;
}
else
{
/* No optimized replace operator found, use default (slow) blitter. */
grub_video_fbblit_blend(target, source, nx, ny, width, height,
offset_x, offset_y);
return;
}
}

if (oper == GRUB_VIDEO_BLIT_REPLACE)
{
/* Try to figure out more optimized version for replace operator. */
Expand Down
28 changes: 19 additions & 9 deletions grub-core/video/fb/fbfill.c
Original file line number Diff line number Diff line change
Expand Up @@ -185,28 +185,38 @@ grub_video_fb_fill_dispatch (struct grub_video_fbblit_info *target,
grub_video_color_t color, int x, int y,
unsigned int width, unsigned int height)
{
grub_video_rect_t orig = {
.x = x,
.y = y,
.width = width,
.height = height
};
grub_video_rect_t fill_rect = grub_video_transform_rectangle (orig, target->mode_info);

/* Try to figure out more optimized version. Note that color is already
mapped to target format so we can make assumptions based on that. */
switch (target->mode_info->bytes_per_pixel)
{
case 4:
grub_video_fbfill_direct32 (target, color, x, y,
width, height);
grub_video_fbfill_direct32 (target, color, fill_rect.x, fill_rect.y,
fill_rect.width, fill_rect.height);
return;
case 3:
grub_video_fbfill_direct24 (target, color, x, y,
width, height);
grub_video_fbfill_direct24 (target, color, fill_rect.x, fill_rect.y,
fill_rect.width, fill_rect.height);
return;
return;
case 2:
grub_video_fbfill_direct16 (target, color, x, y,
width, height);
grub_video_fbfill_direct16 (target, color, fill_rect.x, fill_rect.y,
fill_rect.width, fill_rect.height);
return;
case 1:
grub_video_fbfill_direct8 (target, color, x, y,
width, height);
grub_video_fbfill_direct8 (target, color, fill_rect.x, fill_rect.y,
fill_rect.width, fill_rect.height);
return;
}

/* No optimized version found, use default (slow) filler. */
grub_video_fbfill (target, color, x, y, width, height);
grub_video_fbfill (target, color, fill_rect.x, fill_rect.y,
fill_rect.width, fill_rect.height);
}
68 changes: 68 additions & 0 deletions grub-core/video/fb/fbutil.c
Original file line number Diff line number Diff line change
Expand Up @@ -149,3 +149,71 @@ set_pixel (struct grub_video_fbblit_info *source,
break;
}
}

int trans_x (int x, int y, struct grub_video_mode_info *mode_info)
{
switch (mode_info->rotation)
{
case GRUB_VIDEO_ROTATE_90:
return y;
case GRUB_VIDEO_ROTATE_180:
return -x;
case GRUB_VIDEO_ROTATE_270:
return -y;
case GRUB_VIDEO_ROTATE_NONE:
default:
return x;
}
}

int trans_y(int x, int y, struct grub_video_mode_info *mode_info)
{
switch (mode_info->rotation)
{
case GRUB_VIDEO_ROTATE_90:
return -x;
case GRUB_VIDEO_ROTATE_180:
return -y;
case GRUB_VIDEO_ROTATE_270:
return x;
case GRUB_VIDEO_ROTATE_NONE:
default:
return y;
}
}

grub_video_rect_t
grub_video_transform_rectangle (grub_video_rect_t r,
const struct grub_video_mode_info *mode_info)
{
grub_video_rect_t n;

switch (mode_info->rotation)
{
case GRUB_VIDEO_ROTATE_NONE:
return r;

case GRUB_VIDEO_ROTATE_90:
n.width = r.height;
n.height = r.width;
n.x = r.y;
n.y = mode_info->width - r.x - r.width;
return n;

case GRUB_VIDEO_ROTATE_180:
n.width = r.width;
n.height = r.height;
n.x = mode_info->width - r.x - r.width;
n.y = mode_info->height - r.y - r.height;
return n;

case GRUB_VIDEO_ROTATE_270:
n.width = r.height;
n.height = r.width;
n.x = mode_info->height - r.y - r.height;
n.y = r.x;
return n;
}

return r;
}
Loading