* fb rotation merge directive
@ 2010-01-19 1:57 Michal Suchanek
2010-01-19 11:07 ` Colin Watson
0 siblings, 1 reply; 5+ messages in thread
From: Michal Suchanek @ 2010-01-19 1:57 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 753 bytes --]
Hello
Attaching a merge directive which includes multiple patches which
should bring the possibility to rotate the graphical video output
where the fb library is used for drawing.
As the patches were against r1782 and unlike git the bzr workflow does
not seem to offer a rebase this is probably as good as the format
gets.
The code should work - the modified videotest results seemed OK.
However, packing of different stuff into different files and function
naming may need improvement.
The mode direction specification is very rudimentary - you put some
letters in front of the resolution specification. I did not find a
nice solution for this.
Since there is no imminent release freeze perhaps this could finally
get into grub.
Thanks
Michal
[-- Attachment #2: fbrot.send --]
[-- Type: application/octet-stream, Size: 78389 bytes --]
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: hramrach@heretic-20100119011947-oqnxjyh3l3l12rft
# target_branch: file:///scratch/grub2-bzr/trunk/
# testament_sha1: 11a07ad11c0d1755f1ec69409d9793ce68f86235
# timestamp: 2010-01-19 02:22:28 +0100
# base_revision_id: rmh@aybabtu.com-20100118194339-mq92pqn41kdm1aep
#
# Begin patch
=== modified file 'commands/videotest.c'
--- commands/videotest.c 2010-01-17 16:52:01 +0000
+++ commands/videotest.c 2010-01-19 01:07:06 +0000
@@ -25,6 +25,114 @@
#include <grub/term.h>
#include <grub/command.h>
#include <grub/i18n.h>
+#include <grub/fbtran.h>
+#include <grub/fbfill.h> /*for some reason render target type is defined there */
+#include <grub/bitmap.h>
+
+char leaf_data[] = { 0x00, 0x0f, 0xe0, 0x00,
+ 0x00, 0x7f, 0xfc, 0x00,
+ 0x01, 0xff, 0xff, 0x00,
+ 0x03, 0xff, 0xff, 0x80,
+
+ 0x07, 0xff, 0xff, 0xe0,
+ 0x0f, 0xff, 0xff, 0xf0,
+ 0x1f, 0xff, 0xff, 0xf0,
+ 0x3f, 0xff, 0xff, 0xf8,
+
+ 0x3f, 0xff, 0xff, 0xf8,
+ 0x7f, 0xff, 0xff, 0xfc,
+ 0x7f, 0xff, 0xff, 0xfc,
+ 0xff, 0xff, 0xff, 0xfe,
+
+ 0xff, 0xff, 0xff, 0xfe,
+ 0xff, 0xff, 0xff, 0xfe,
+ 0xff, 0xff, 0xff, 0xfe,
+ 0xff, 0xff, 0xff, 0xfe,
+
+ 0xff, 0xff, 0xff, 0xfe,
+ 0xff, 0xff, 0xff, 0xfe,
+ 0xff, 0xff, 0xff, 0xfe,
+ 0xff, 0xff, 0xff, 0xfe,
+
+ 0xff, 0xff, 0xff, 0xfc,
+ 0xff, 0xff, 0xff, 0xfc,
+ 0xff, 0xff, 0xff, 0xf8,
+ 0xff, 0xff, 0xff, 0xf8,
+
+ 0xff, 0xff, 0xff, 0xf0,
+ 0xff, 0xff, 0xff, 0xe0,
+ 0xff, 0xff, 0xff, 0xc0,
+ 0xff, 0xff, 0xff, 0x80,
+
+ 0xff, 0xff, 0xff, 0x00,
+ 0xff, 0xff, 0xfc, 0x00,
+ 0xff, 0xff, 0xe0, 0x00,
+ 0xff, 0x00, 0x00, 0x00 };
+#define LEAF_SIZE 32
+
+struct grub_video_bitmap leaves[4];
+
+static void init_leaves(void)
+{
+
+ leaves[0].mode_info.width = LEAF_SIZE;
+ leaves[0].mode_info.height = LEAF_SIZE;
+ leaves[0].mode_info.transform = FB_TRAN_EAST;
+ leaves[0].mode_info.mode_type =
+ (1 << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
+ | GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP;
+ leaves[0].mode_info.blit_format = GRUB_VIDEO_BLIT_FORMAT_1BIT_PACKED;
+ leaves[0].mode_info.bpp = 1;
+ leaves[0].mode_info.bytes_per_pixel = 0;
+ leaves[0].mode_info.pitch = LEAF_SIZE;
+ leaves[0].mode_info.number_of_colors = 2;
+ leaves[0].mode_info.bg_red = 128;
+ leaves[0].mode_info.fg_red = 255;
+ leaves[0].mode_info.bg_green = 128;
+ leaves[0].mode_info.bg_alpha = 128;
+ leaves[0].mode_info.fg_alpha = 255;
+ leaves[0].mode_info.fg_green = 255;
+ leaves[0].mode_info.bg_blue = 128;
+ leaves[0].mode_info.fg_blue = 255;
+ leaves[0].data = leaf_data;
+
+ grub_memcpy(&leaves[1], leaves, sizeof(leaves[0]));
+ grub_memcpy(&leaves[2], leaves, 2* sizeof(leaves[0]));
+ leaves[1].mode_info.transform = FB_TRAN_NORTH;
+ leaves[2].mode_info.transform = FB_TRAN_WEST;
+ leaves[3].mode_info.transform = FB_TRAN_SOUTH;
+ leaves[0].mode_info.fg_red = 0;
+ leaves[1].mode_info.fg_green = 0;
+ leaves[2].mode_info.fg_blue = 0;
+ leaves[3].mode_info.fg_blue = 0;
+ leaves[3].mode_info.fg_green = 0;
+ leaves[3].mode_info.fg_red = 0;
+}
+
+#define BORDER 20
+
+static void draw_leaves(void)
+{
+ grub_font_t sans;
+ grub_video_color_t text_color, fill_color;
+
+ sans = grub_font_get ("Helvetica Bold 14");
+ text_color = grub_video_map_rgb (255, 255, 255);
+ fill_color = grub_video_map_rgba (0, 192, 0, 192);
+
+ grub_video_fill_rect(fill_color, 0, 0, BORDER, BORDER);
+ grub_video_blit_bitmap(leaves, GRUB_VIDEO_BLIT_REPLACE, BORDER, BORDER, 0, 0, LEAF_SIZE, LEAF_SIZE);
+ grub_video_blit_bitmap(leaves + 1, GRUB_VIDEO_BLIT_REPLACE, BORDER+LEAF_SIZE, BORDER, 0, 0, LEAF_SIZE, LEAF_SIZE);
+ grub_video_blit_bitmap(leaves + 2, GRUB_VIDEO_BLIT_REPLACE, BORDER+LEAF_SIZE, BORDER+LEAF_SIZE, 0, 0, LEAF_SIZE, LEAF_SIZE);
+ grub_video_blit_bitmap(leaves + 3, GRUB_VIDEO_BLIT_REPLACE, BORDER, BORDER+LEAF_SIZE, 0, 0, LEAF_SIZE, LEAF_SIZE);
+ grub_video_blit_bitmap(leaves, GRUB_VIDEO_BLIT_BLEND, BORDER+LEAF_SIZE*2, BORDER, 0, 0, LEAF_SIZE, LEAF_SIZE);
+ grub_video_blit_bitmap(leaves + 1, GRUB_VIDEO_BLIT_BLEND, BORDER+LEAF_SIZE*3, BORDER, 0, 0, LEAF_SIZE, LEAF_SIZE);
+ grub_video_blit_bitmap(leaves + 2, GRUB_VIDEO_BLIT_BLEND, BORDER+LEAF_SIZE*3, BORDER+LEAF_SIZE, 0, 0, LEAF_SIZE, LEAF_SIZE);
+ grub_video_blit_bitmap(leaves + 3, GRUB_VIDEO_BLIT_BLEND, BORDER+LEAF_SIZE*2, BORDER+LEAF_SIZE, 0, 0, LEAF_SIZE, LEAF_SIZE);
+ grub_video_fill_rect(fill_color, BORDER+LEAF_SIZE*4, BORDER, LEAF_SIZE*2, LEAF_SIZE*2);
+ grub_font_draw_string ("Leaves", sans, text_color, BORDER + LEAF_SIZE / 2, 4*LEAF_SIZE + BORDER);
+
+}
static grub_err_t
grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
@@ -33,10 +141,10 @@
{
grub_err_t err;
grub_video_color_t color;
- unsigned int x;
- unsigned int y;
- unsigned int width;
- unsigned int height;
+ int x;
+ int y;
+ int width;
+ int height;
int i;
grub_font_t sansbig;
grub_font_t sans;
@@ -52,7 +160,49 @@
if (err)
return err;
- grub_video_get_viewport (&x, &y, &width, &height);
+ if (1) /* TODO: check that we are actually using a video_fb target */
+ {
+ struct grub_video_fbrender_target * tgt;
+ grub_video_fb_get_active_render_target(&tgt);
+
+ init_leaves();
+ grub_video_get_viewport (&x, &y, &width, &height);
+
+ draw_leaves();
+
+ tgt->mode_info.transform=FB_TRAN_MIRROR;
+ draw_leaves();
+
+ tgt->mode_info.transform=FB_TRAN_FLIP|FB_TRAN_MIRROR;
+ draw_leaves();
+
+ tgt->mode_info.transform=FB_TRAN_FLIP;
+ draw_leaves();
+
+ grub_getkey ();
+
+ tgt->mode_info.transform=FB_TRAN_NORTH;
+ color = grub_video_map_rgb (0, 0, 0);
+ grub_video_fill_rect (color, 0, 0, width, height);
+ draw_leaves();
+
+ tgt->mode_info.transform=FB_TRAN_EAST;
+ grub_video_set_viewport (x, y, height, width);
+ draw_leaves();
+
+ tgt->mode_info.transform=FB_TRAN_SOUTH;
+ grub_video_set_viewport (x, y, width, height);
+ draw_leaves();
+
+ tgt->mode_info.transform=FB_TRAN_WEST;
+ grub_video_set_viewport (x, y, height, width);
+ draw_leaves();
+
+ tgt->mode_info.transform=FB_TRAN_NORTH;
+ grub_video_set_viewport (x, y, width, height);
+
+ grub_getkey ();
+ }
grub_video_create_render_target (&text_layer, width, height,
GRUB_VIDEO_MODE_TYPE_RGB
@@ -118,7 +268,8 @@
str =
"Unicode test: happy\xE2\x98\xBA \xC2\xA3 5.00"
" \xC2\xA1\xCF\x84\xC3\xA4u! "
- " \xE2\x84\xA4\xE2\x8A\x87\xE2\x84\x9D";
+ " \xE2\x84\xA4\xE2\x8A\x87\xE2\x84\x9D"
+ " \343\201\202!" /* hiragana letter a */;
color = grub_video_map_rgb (128, 128, 255);
/* All characters in the string exist in the 'Fixed 20' (10x20) font. */
=== modified file 'font/font.c'
--- font/font.c 2009-12-24 22:53:05 +0000
+++ font/font.c 2010-01-19 00:41:06 +0000
@@ -987,8 +987,10 @@
if (glyph->width == 0 || glyph->height == 0)
return GRUB_ERR_NONE;
+ /* TODO: add support for bitmaps to create_bitmap */
glyph_bitmap.mode_info.width = glyph->width;
glyph_bitmap.mode_info.height = glyph->height;
+ glyph_bitmap.mode_info.transform = 0;
glyph_bitmap.mode_info.mode_type =
(1 << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
| GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP;
=== modified file 'include/grub/fbblit.h'
--- include/grub/fbblit.h 2009-08-28 13:54:20 +0000
+++ include/grub/fbblit.h 2010-01-18 22:01:49 +0000
@@ -28,7 +28,7 @@
grub_video_fbblit_replace (struct grub_video_fbblit_info *dst,
struct grub_video_fbblit_info *src,
int x, int y, int width, int height,
- int offset_x, int offset_y);
+ int offset_x, int offset_y, int transform);
void
grub_video_fbblit_replace_directN (struct grub_video_fbblit_info *dst,
@@ -94,7 +94,7 @@
grub_video_fbblit_blend (struct grub_video_fbblit_info *dst,
struct grub_video_fbblit_info *src,
int x, int y, int width, int height,
- int offset_x, int offset_y);
+ int offset_x, int offset_y, int transform);
void
grub_video_fbblit_blend_BGRA8888_RGBA8888 (struct grub_video_fbblit_info *dst,
=== modified file 'include/grub/fbfill.h'
--- include/grub/fbfill.h 2009-08-18 17:26:35 +0000
+++ include/grub/fbfill.h 2010-01-18 21:58:36 +0000
@@ -32,10 +32,10 @@
struct
{
- unsigned int x;
- unsigned int y;
- unsigned int width;
- unsigned int height;
+ int x;
+ int y;
+ int width;
+ int height;
} viewport;
/* Indicates whether the data has been allocated by us and must be freed
=== added file 'include/grub/fbtran.h'
--- include/grub/fbtran.h 1970-01-01 00:00:00 +0000
+++ include/grub/fbtran.h 2010-01-18 23:24:40 +0000
@@ -0,0 +1,220 @@
+/*
+ * GRUB -- GRand Unified Bootloader
+ * Copyright (C) 2009 Free Software Foundation, Inc.
+ *
+ * GRUB is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GRUB is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+
+#ifndef GRUB_FBTRAN_HEADER
+#define GRUB_FBTRAN_HEADER 1
+
+#include <grub/video.h>
+#include <grub/video_fb.h>
+#include <grub/misc.h>
+
+/* NOTE: This header is private header for fb driver and should not be used
+ in other parts of the code. */
+
+/* Supported operations are simple and easy to understand.
+ * MIRROR | swap image across (around) the vertical axis
+ * FLIP - swap image across the horizontal axis - upside down
+ * SWAP / swap image across the x=y axis - swap the x and y coordinates
+ *
+ * All the operations are self-negating.
+ * || = -- = // = 0 (identity)
+ *
+ * | and - are commutative.
+ *
+ * |- = -|
+ *
+ * The relationship between \ and |,- is more peculiar:
+ *
+ * \- = |\
+ * \| = -\
+ *
+ * The typical display operations used to adjust displayed picture for use with
+ * rotated display equipment and/or mirrors are FLIP, MIRROR, and rot90,
+ * rot180, rot270.
+ *
+ * The way this rotation works is somewhat confusing. If we say "rotate left"
+ * does that mean to rotate the screen left (and rotate the picture right to
+ * compensate) or the other way around?
+ *
+ * So I will try to explain in different terms for clarity.
+ * Let's say that what you normally get is "facing the north side of the
+ * screen" or "N" for short. If you turn the screen anti-clockwise you get E,
+ * etc.
+ *
+ * If we apply the simple transforms (MIRROR, FLIP) first to get the corretct
+ * picture when facing the east side of the screen we need the -\ transform.
+ *
+ * E = -rot90 = -\
+ * S = -rot180 = -\-\ = -|\\ = -|
+ * W = -rot270 = -|-\ = |\
+ *
+ * Forward transform is from user visible cordinates to framebuffer memory coordinates.
+ */
+
+#define FB_TRAN_SWAP 1
+#define FB_TRAN_FLIP 2
+#define FB_TRAN_MIRROR 4
+#define FB_TRAN_MASK 7
+#define FB_TRAN_SIMPLE 6
+#define FB_TRAN_NORTH 0
+#define FB_TRAN_EAST (FB_TRAN_FLIP | FB_TRAN_SWAP)
+#define FB_TRAN_SOUTH (FB_TRAN_FLIP | FB_TRAN_MIRROR)
+#define FB_TRAN_WEST (FB_TRAN_MIRROR | FB_TRAN_SWAP)
+
+/* internal function used for transforms */
+static inline int fb_tran_swap_tran(int transform)
+{
+ int old = transform;
+ transform &= FB_TRAN_SWAP;
+ if (old & FB_TRAN_MIRROR)
+ transform ^= FB_TRAN_FLIP;
+ if (old & FB_TRAN_FLIP)
+ transform ^= FB_TRAN_MIRROR;
+ return transform;
+}
+
+/* Return a new bitmap for the transformation which is the result of applying
+ * the transformations present in the first bitmap, and then transformations in
+ * the second bitmap. Should work on modes that have the same width and height
+ * at the point the transfom is appended. In other words: don't use.*/
+static inline int fb_tran_append(int transform_first, int transform_second)
+{
+ return (transform_first & FB_TRAN_SWAP) ?
+ (transform_first ^ fb_tran_swap_tran(transform_second)) :
+ (transform_first ^ transform_second);
+}
+
+/* Return a bitmap for transformation that negates the specified transformation. */
+static inline int fb_tran_invert(int transform)
+{
+ return (transform & FB_TRAN_SWAP) ? fb_tran_swap_tran(transform) : transform;
+}
+
+/* Create a bitmap for transformation that has to be applied after the first
+ * transformation to obtain the second transformation. */
+static inline int fb_tran_diff(int transform_first, int transform_second)
+{
+ return fb_tran_append(fb_tran_invert(transform_first), transform_second);
+}
+
+/* transform screen dimensions */
+static inline grub_err_t fb_tran_dim_back(int * width, int * height, int transform)
+{
+ if (transform & FB_TRAN_SWAP)
+ grub_swap_int(width, height);
+ return GRUB_ERR_NONE;
+}
+
+static inline grub_err_t fb_tran_dim(unsigned * width, unsigned * height, int transform)
+{
+ if (transform & FB_TRAN_SWAP)
+ grub_swap_unsigned(width, height);
+ return GRUB_ERR_NONE;
+}
+
+/* internal - apply coordinate transform to a point */
+static inline grub_err_t fb_tran_point_intern(int *x, int *y, int width, int height, int transform, int user_coordinates)
+{
+ if (user_coordinates && (transform & FB_TRAN_SWAP))
+ grub_swap_int(&width, &height);
+ if (transform & FB_TRAN_MIRROR)
+ *x = width -1 - *x;
+ if (transform & FB_TRAN_FLIP)
+ *y = height -1 - *y;
+ if (transform & FB_TRAN_SWAP)
+ grub_swap_int(x, y);
+ return GRUB_ERR_NONE;
+}
+
+/* apply coordinate transform to a point */
+static inline grub_err_t fb_tran_point(int *x, int *y, const struct grub_video_mode_info *mode)
+{
+ return fb_tran_point_intern(x, y, mode->width, mode->height, mode->transform, 1);
+}
+
+/* apply reverse coordinate transform to a point */
+static inline grub_err_t fb_tran_point_back(int *x, int *y, const struct grub_video_mode_info *mode)
+{
+ return fb_tran_point_intern(x, y, mode->width, mode->height, fb_tran_invert(mode->transform), 0);
+}
+
+/* internal - apply coordinate transform to a rectangle */
+static inline grub_err_t fb_tran_rect_intern(int *x, int *y, int *width, int *height, int mode_width, int mode_height, int transform, int user_coordinates)
+{
+ int x2, y2;
+ grub_fb_norm_rect(x, y, width, height);
+ x2 = *x + *width;
+ y2 = *y + *height;
+ fb_tran_point_intern(x, y, mode_width, mode_height, transform, user_coordinates);
+ fb_tran_point_intern(&x2, &y2, mode_width, mode_height, transform, user_coordinates);
+ if(*x > x2)
+ {
+ grub_swap_int(x, &x2);
+ (*x)++;
+ x2++;
+ }
+ if(*y > y2)
+ {
+ grub_swap_int(y, &y2);
+ (*y)++;
+ y2++;
+ }
+ *width = x2 - *x;
+ *height = y2 - *y;
+ return GRUB_ERR_NONE;
+}
+
+/* apply coordinate transform to a rectangle */
+static inline grub_err_t fb_tran_rect(int *x, int *y, int *width, int *height, const struct grub_video_mode_info *mode)
+{
+ return fb_tran_rect_intern(x, y, width, height, mode->width, mode->height, mode->transform,1);
+}
+
+/* apply reverse coordinate transform to a rectangle */
+static inline grub_err_t fb_tran_rect_back(int *x, int *y, int *width, int *height, const struct grub_video_mode_info *mode)
+{
+ return fb_tran_rect_intern(x, y, width, height, mode->width, mode->height, fb_tran_invert(mode->transform),0);
+}
+
+/* Return bitmap of transform that is to be applied during blit.
+ * The source and target point are transformed to the framebuffer coordinates
+ * so that src_x,src_y is copied to x,y.
+ */
+static inline grub_err_t fb_tran_blit(int *src_x, int *src_y, int *width, int *height,
+ int *x, int *y, int *transform,
+ const struct grub_video_mode_info *source_mode,
+ const struct grub_video_mode_info *target_mode)
+{
+ int sx1 = *src_x;
+ int sy1 = *src_y;
+ int sx2, sy2;
+
+ fb_tran_rect(src_x, src_y, width, height, source_mode);
+ sx2 = *src_x;
+ sy2 = *src_y;
+ fb_tran_point_back(&sx2, &sy2, source_mode);
+ *x += sx2 - sx1;
+ *y += sy2 - sy1;
+ fb_tran_point(x, y, target_mode);
+ *transform = fb_tran_diff(source_mode->transform, target_mode->transform);
+ return GRUB_ERR_NONE;
+}
+
+
+#endif /* ! GRUB_FBTRAN_HEADER */
=== modified file 'include/grub/misc.h'
--- include/grub/misc.h 2010-01-05 15:27:41 +0000
+++ include/grub/misc.h 2010-01-19 00:46:45 +0000
@@ -213,6 +213,9 @@
/* Inline functions. */
+static inline void grub_swap_int(int *a, int *b) { int tmp = *a; *a = *b; *b = tmp; }
+static inline void grub_swap_unsigned(unsigned *a, unsigned *b) { unsigned tmp = *a; *a = *b; *b = tmp; }
+
static inline unsigned int
grub_abs (int x)
{
@@ -231,6 +234,15 @@
return y;
}
+static inline long
+grub_min (long x, long y)
+{
+ if (x > y)
+ return y;
+ else
+ return x;
+}
+
/* Rounded-up division */
static inline unsigned int
grub_div_roundup (unsigned int x, unsigned int y)
=== modified file 'include/grub/video.h'
--- include/grub/video.h 2010-01-17 16:52:01 +0000
+++ include/grub/video.h 2010-01-19 01:07:06 +0000
@@ -149,6 +149,8 @@
grub_uint8_t fg_green;
grub_uint8_t fg_blue;
grub_uint8_t fg_alpha;
+
+ int transform;
};
struct grub_video_palette_data
@@ -180,7 +182,8 @@
grub_err_t (*fini) (void);
grub_err_t (*setup) (unsigned int width, unsigned int height,
- unsigned int mode_type, unsigned int mode_mask);
+ unsigned int mode_type, unsigned int mode_mask,
+ int transform);
grub_err_t (*get_info) (struct grub_video_mode_info *mode_info);
@@ -193,11 +196,9 @@
grub_err_t (*get_palette) (unsigned int start, unsigned int count,
struct grub_video_palette_data *palette_data);
- grub_err_t (*set_viewport) (unsigned int x, unsigned int y,
- unsigned int width, unsigned int height);
+ grub_err_t (*set_viewport) (int x, int y, int width, int height);
- grub_err_t (*get_viewport) (unsigned int *x, unsigned int *y,
- unsigned int *width, unsigned int *height);
+ grub_err_t (*get_viewport) (int *x, int *y, int *width, int *height);
grub_video_color_t (*map_color) (grub_uint32_t color_name);
@@ -212,17 +213,17 @@
grub_uint8_t *blue, grub_uint8_t *alpha);
grub_err_t (*fill_rect) (grub_video_color_t color, int x, int y,
- unsigned int width, unsigned int height);
+ int width, int height);
grub_err_t (*blit_bitmap) (struct grub_video_bitmap *bitmap,
enum grub_video_blit_operators oper,
int x, int y, int offset_x, int offset_y,
- unsigned int width, unsigned int height);
+ int width, int height);
grub_err_t (*blit_render_target) (struct grub_video_render_target *source,
enum grub_video_blit_operators oper,
int x, int y, int offset_x, int offset_y,
- unsigned int width, unsigned int height);
+ int width, int height);
grub_err_t (*scroll) (grub_video_color_t color, int dx, int dy);
@@ -267,11 +268,11 @@
grub_err_t grub_video_get_palette (unsigned int start, unsigned int count,
struct grub_video_palette_data *palette_data);
-grub_err_t grub_video_set_viewport (unsigned int x, unsigned int y,
- unsigned int width, unsigned int height);
+grub_err_t grub_video_set_viewport (int x, int y,
+ int width, int height);
-grub_err_t grub_video_get_viewport (unsigned int *x, unsigned int *y,
- unsigned int *width, unsigned int *height);
+grub_err_t grub_video_get_viewport (int *x, int *y,
+ int *width, int *height);
grub_video_color_t grub_video_map_color (grub_uint32_t color_name);
@@ -286,19 +287,18 @@
grub_uint8_t *blue, grub_uint8_t *alpha);
grub_err_t grub_video_fill_rect (grub_video_color_t color, int x, int y,
- unsigned int width, unsigned int height);
+ int width, int height);
grub_err_t grub_video_blit_bitmap (struct grub_video_bitmap *bitmap,
enum grub_video_blit_operators oper,
int x, int y, int offset_x, int offset_y,
- unsigned int width, unsigned int height);
+ int width, int height);
grub_err_t grub_video_blit_render_target (struct grub_video_render_target *source,
enum grub_video_blit_operators oper,
int x, int y,
int offset_x, int offset_y,
- unsigned int width,
- unsigned int height);
+ int width, int height);
grub_err_t grub_video_scroll (grub_video_color_t color, int dx, int dy);
=== modified file 'include/grub/video_fb.h'
--- include/grub/video_fb.h 2009-08-17 13:34:24 +0000
+++ include/grub/video_fb.h 2010-01-18 21:58:36 +0000
@@ -16,6 +16,12 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
+/* SPECIAL NOTE!
+
+ - In this driver we assume that every memory can be accessed by same memory
+ bus. If there are different address spaces do not use this code as a base
+ code for other archs. */
+
#ifndef GRUB_VIDEO_FB_HEADER
#define GRUB_VIDEO_FB_HEADER 1
@@ -30,6 +36,22 @@
struct grub_video_fbrender_target;
+/* make width and height of a rectangle non-negative */
+static inline grub_err_t grub_fb_norm_rect(int *x, int *y, int *width, int *height)
+{
+ if(*width < 0)
+ {
+ *width = -*width;
+ *x -= *width - 1;
+ }
+ if(*height < 0)
+ {
+ *height = -*height;
+ *y -= *height - 1;
+ }
+ return GRUB_ERR_NONE;
+}
+
#define GRUB_VIDEO_FBSTD_NUMCOLORS 16
extern struct grub_video_palette_data grub_video_fbstd_colors[GRUB_VIDEO_FBSTD_NUMCOLORS];
@@ -49,11 +71,11 @@
grub_video_fb_set_palette (unsigned int start, unsigned int count,
struct grub_video_palette_data *palette_data);
grub_err_t
-grub_video_fb_set_viewport (unsigned int x, unsigned int y,
- unsigned int width, unsigned int height);
+grub_video_fb_set_viewport (int x, int y,
+ int width, int height);
grub_err_t
-grub_video_fb_get_viewport (unsigned int *x, unsigned int *y,
- unsigned int *width, unsigned int *height);
+grub_video_fb_get_viewport (int *x, int *y,
+ int *width, int *height);
grub_video_color_t
grub_video_fb_map_color (grub_uint32_t color_name);
@@ -79,19 +101,19 @@
grub_err_t
grub_video_fb_fill_rect (grub_video_color_t color, int x, int y,
- unsigned int width, unsigned int height);
+ int width, int height);
grub_err_t
grub_video_fb_blit_bitmap (struct grub_video_bitmap *bitmap,
enum grub_video_blit_operators oper, int x, int y,
int offset_x, int offset_y,
- unsigned int width, unsigned int height);
+ int width, int height);
grub_err_t
grub_video_fb_blit_render_target (struct grub_video_fbrender_target *source,
enum grub_video_blit_operators oper,
int x, int y, int offset_x, int offset_y,
- unsigned int width, unsigned int height);
+ int width, int height);
grub_err_t
grub_video_fb_scroll (grub_video_color_t color, int dx, int dy);
=== modified file 'term/gfxterm.c'
--- term/gfxterm.c 2010-01-17 16:52:01 +0000
+++ term/gfxterm.c 2010-01-19 01:07:06 +0000
@@ -105,6 +105,9 @@
static struct grub_video_mode_info mode_info;
+static int view_width;
+static int view_height;
+
static struct grub_video_render_target *text_layer;
static unsigned int bitmap_width;
@@ -253,6 +256,7 @@
grub_video_color_t color;
int width;
int height;
+ int view_x, view_y;
grub_err_t err;
/* Select the font to use. */
@@ -283,14 +287,15 @@
if (err)
return err;
+ grub_video_get_viewport(&view_x, &view_y, &view_width, &view_height);
/* Make sure screen is black. */
color = grub_video_map_rgb (0, 0, 0);
- grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height);
+ grub_video_fill_rect (color, 0, 0, view_width, view_height);
bitmap = 0;
/* Leave borders for virtual screen. */
- width = mode_info.width - (2 * DEFAULT_BORDER_WIDTH);
- height = mode_info.height - (2 * DEFAULT_BORDER_WIDTH);
+ width = view_width - (2 * DEFAULT_BORDER_WIDTH);
+ height = view_height - (2 * DEFAULT_BORDER_WIDTH);
/* Create virtual screen. */
if (grub_virtual_screen_setup (DEFAULT_BORDER_WIDTH, DEFAULT_BORDER_WIDTH,
@@ -302,7 +307,7 @@
/* Mark whole screen as dirty. */
dirty_region_reset ();
- dirty_region_add (0, 0, mode_info.width, mode_info.height);
+ dirty_region_add (0, 0, view_width, view_height);
return (grub_errno = GRUB_ERR_NONE);
}
@@ -810,7 +815,7 @@
/* Clear text layer. */
grub_video_set_active_render_target (text_layer);
color = virtual_screen.bg_color;
- grub_video_fill_rect (color, 0, 0, mode_info.width, mode_info.height);
+ grub_video_fill_rect (color, 0, 0, view_width, view_height);
grub_video_set_active_render_target (GRUB_VIDEO_RENDER_TARGET_DISPLAY);
/* Mark virtual screen to be redrawn. */
@@ -896,7 +901,7 @@
/* Mark whole screen as dirty. */
dirty_region_reset ();
- dirty_region_add (0, 0, mode_info.width, mode_info.height);
+ dirty_region_add (0, 0, view_width, view_height);
}
/* If filename was provided, try to load that. */
@@ -916,7 +921,7 @@
/* Mark whole screen as dirty. */
dirty_region_reset ();
- dirty_region_add (0, 0, mode_info.width, mode_info.height);
+ dirty_region_add (0, 0, view_width, view_height);
}
}
=== modified file 'video/bitmap.c'
--- video/bitmap.c 2009-12-24 22:53:05 +0000
+++ video/bitmap.c 2010-01-19 00:41:06 +0000
@@ -75,6 +75,7 @@
mode_info->width = width;
mode_info->height = height;
mode_info->blit_format = blit_format;
+ mode_info->transform = 0;
switch (blit_format)
{
=== modified file 'video/efi_gop.c'
--- video/efi_gop.c 2010-01-17 16:52:01 +0000
+++ video/efi_gop.c 2010-01-19 01:19:47 +0000
@@ -185,7 +185,8 @@
static grub_err_t
grub_video_gop_setup (unsigned int width, unsigned int height,
- unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused)))
+ unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused)),
+ int transform)
{
unsigned int depth;
struct grub_efi_gop_mode_info *info = NULL;
@@ -287,6 +288,7 @@
grub_dprintf ("video", "GOP: couldn't fill mode info\n");
return err;
}
+ framebuffer.mode_info.transform = transform;
framebuffer.ptr = (void *) (grub_addr_t) gop->mode->fb_base;
=== modified file 'video/efi_uga.c'
--- video/efi_uga.c 2010-01-17 16:52:01 +0000
+++ video/efi_uga.c 2010-01-19 01:07:06 +0000
@@ -198,7 +198,8 @@
static grub_err_t
grub_video_uga_setup (unsigned int width, unsigned int height,
- unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused)))
+ unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused)),
+ int transform)
{
unsigned int depth;
int found = 0;
@@ -231,6 +232,7 @@
grub_err_t err;
framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB;
+ framebuffer.mode_info.transform = transform;
framebuffer.mode_info.bpp = 32;
framebuffer.mode_info.bytes_per_pixel = 4;
framebuffer.mode_info.number_of_colors = 256; /* TODO: fix me. */
=== modified file 'video/fb/fbblit.c'
--- video/fb/fbblit.c 2009-08-28 13:54:20 +0000
+++ video/fb/fbblit.c 2010-01-18 22:01:49 +0000
@@ -16,13 +16,7 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
-/* SPECIAL NOTES!
-
- Please note following when reading the code below:
-
- - In this driver we assume that every memory can be accessed by same memory
- bus. If there are different address spaces do not use this code as a base
- code for other archs.
+/* SPECIAL NOTE!
- Every function in this code assumes that bounds checking has been done in
previous phase and they are opted out in here. */
@@ -33,16 +27,19 @@
#include <grub/misc.h>
#include <grub/types.h>
#include <grub/video.h>
+#include <grub/fbtran.h>
/* Generic replacing blitter (slow). Works for every supported format. */
void
grub_video_fbblit_replace (struct grub_video_fbblit_info *dst,
struct grub_video_fbblit_info *src,
int x, int y, int width, int height,
- int offset_x, int offset_y)
+ int offset_x, int offset_y, int transform)
{
int i;
int j;
+ int dx = (transform & FB_TRAN_MIRROR) ? -1 : 1;
+ int dy = (transform & FB_TRAN_FLIP) ? -1 : 1;
grub_uint8_t src_red;
grub_uint8_t src_green;
grub_uint8_t src_blue;
@@ -62,8 +59,11 @@
dst_color = grub_video_fb_map_rgba (src_red, src_green,
src_blue, src_alpha);
- set_pixel (dst, x + i, y + j, dst_color);
- }
+ if (transform & FB_TRAN_SWAP)
+ set_pixel (dst, x + j*dy, y + i*dx, dst_color);
+ else
+ set_pixel (dst, x + i*dx, y + j*dy, dst_color);
+ }
}
}
@@ -711,10 +711,12 @@
grub_video_fbblit_blend (struct grub_video_fbblit_info *dst,
struct grub_video_fbblit_info *src,
int x, int y, int width, int height,
- int offset_x, int offset_y)
+ int offset_x, int offset_y, int transform)
{
int i;
int j;
+ int dx = (transform & FB_TRAN_MIRROR) ? -1 : 1;
+ int dy = (transform & FB_TRAN_FLIP) ? -1 : 1;
for (j = 0; j < height; j++)
{
@@ -741,12 +743,17 @@
if (src_alpha == 255)
{
dst_color = grub_video_fb_map_rgba (src_red, src_green,
- src_blue, src_alpha);
- set_pixel (dst, x + i, y + j, dst_color);
+ src_blue, src_alpha);
+ if (transform & FB_TRAN_SWAP)
+ set_pixel (dst, x + j*dy, y + i*dx, dst_color);
+ else
+ set_pixel (dst, x + i*dx, y + j*dy, dst_color);
continue;
}
- dst_color = get_pixel (dst, x + i, y + j);
+ dst_color = (transform & FB_TRAN_SWAP) ?
+ get_pixel (dst, x + j*dy, y + i*dx) :
+ get_pixel (dst, x + i*dx, y + j*dy) ;
grub_video_fb_unmap_color_int (dst, dst_color, &dst_red,
&dst_green, &dst_blue, &dst_alpha);
@@ -762,7 +769,10 @@
dst_color = grub_video_fb_map_rgba (dst_red, dst_green, dst_blue,
dst_alpha);
- set_pixel (dst, x + i, y + j, dst_color);
+ if (transform & FB_TRAN_SWAP)
+ set_pixel (dst, x + j*dy, y + i*dx, dst_color);
+ else
+ set_pixel (dst, x + i*dx, y + j*dy, dst_color);
}
}
}
=== modified file 'video/fb/fbfill.c'
--- video/fb/fbfill.c 2009-08-14 12:41:58 +0000
+++ video/fb/fbfill.c 2010-01-18 21:57:17 +0000
@@ -16,13 +16,7 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
-/* SPECIAL NOTES!
-
- Please note following when reading the code below:
-
- - In this driver we assume that every memory can be accessed by same memory
- bus. If there are different address spaces do not use this code as a base
- code for other archs.
+/* SPECIAL NOTE!
- Every function in this code assumes that bounds checking has been done in
previous phase and they are opted out in here. */
=== modified file 'video/fb/fbutil.c'
--- video/fb/fbutil.c 2009-08-18 17:26:35 +0000
+++ video/fb/fbutil.c 2010-01-18 21:57:17 +0000
@@ -16,13 +16,7 @@
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
-/* SPECIAL NOTES!
-
- Please note following when reading the code below:
-
- - In this driver we assume that every memory can be accessed by same memory
- bus. If there are different address spaces do not use this code as a base
- code for other archs.
+/* SPECIAL NOTE!
- Every function in this code assumes that bounds checking has been done in
previous phase and they are opted out in here. */
=== modified file 'video/fb/video_fb.c'
--- video/fb/video_fb.c 2009-12-24 22:53:05 +0000
+++ video/fb/video_fb.c 2010-01-19 00:41:06 +0000
@@ -23,6 +23,7 @@
#include <grub/fbblit.h>
#include <grub/fbfill.h>
#include <grub/fbutil.h>
+#include <grub/fbtran.h>
#include <grub/bitmap.h>
static struct grub_video_fbrender_target *render_target;
@@ -117,27 +118,30 @@
}
grub_err_t
-grub_video_fb_set_viewport (unsigned int x, unsigned int y,
- unsigned int width, unsigned int height)
+grub_video_fb_set_viewport (int x, int y, int width, int height)
{
+ grub_fb_norm_rect(&x, &y, &width, &height);
/* Make sure viewport is withing screen dimensions. If viewport was set
to be out of the region, mark its size as zero. */
- if (x > render_target->mode_info.width)
+ int mode_width = render_target->mode_info.width;
+ int mode_height = render_target->mode_info.height;
+ fb_tran_dim_back(&mode_width, &mode_height, render_target->mode_info.transform);
+ if (x > mode_width)
{
x = 0;
width = 0;
}
- if (y > render_target->mode_info.height)
+ if (y > mode_height)
{
y = 0;
height = 0;
}
- if (x + width > render_target->mode_info.width)
+ if (x + width > mode_width)
width = render_target->mode_info.width - x;
- if (y + height > render_target->mode_info.height)
+ if (y + height > mode_height)
height = render_target->mode_info.height - y;
render_target->viewport.x = x;
@@ -149,8 +153,7 @@
}
grub_err_t
-grub_video_fb_get_viewport (unsigned int *x, unsigned int *y,
- unsigned int *width, unsigned int *height)
+grub_video_fb_get_viewport (int *x, int *y, int *width, int *height)
{
if (x) *x = render_target->viewport.x;
if (y) *y = render_target->viewport.y;
@@ -399,14 +402,15 @@
grub_err_t
grub_video_fb_fill_rect (grub_video_color_t color, int x, int y,
- unsigned int width, unsigned int height)
+ int width, int height)
{
struct grub_video_fbblit_info target;
+ grub_fb_norm_rect(&x, &y, &width, &height);
/* Make sure there is something to do. */
- if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0))
+ if ((x >= render_target->viewport.width) || (x + width < 0))
return GRUB_ERR_NONE;
- if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0))
+ if ((y >= render_target->viewport.height) || (y + height < 0))
return GRUB_ERR_NONE;
/* Do not allow drawing out of viewport. */
@@ -434,6 +438,9 @@
target.mode_info = &render_target->mode_info;
target.data = render_target->data;
+ /* transform coordinates */
+ fb_tran_rect(&x, &y, &width, &height, &render_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. */
if (target.mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_BGRA_8888)
@@ -485,11 +492,15 @@
common_blitter (struct grub_video_fbblit_info *target,
struct grub_video_fbblit_info *source,
enum grub_video_blit_operators oper, int x, int y,
- unsigned int width, unsigned int height,
+ int width, int height,
int offset_x, int offset_y)
{
+ int transform;
+ fb_tran_blit(&offset_x, &offset_y, &width, &height, &x, &y, &transform,
+ source->mode_info, target->mode_info);
if (oper == GRUB_VIDEO_BLIT_REPLACE)
{
+ if (!transform) {
/* Try to figure out more optimized version for replace operator. */
if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888)
{
@@ -618,13 +629,15 @@
return;
}
}
+ } /* !transform */
/* No optimized replace operator found, use default (slow) blitter. */
grub_video_fbblit_replace (target, source, x, y, width, height,
- offset_x, offset_y);
+ offset_x, offset_y, transform);
}
else
{
+ if (!transform) {
/* Try to figure out more optimized blend operator. */
if (source->mode_info->blit_format == GRUB_VIDEO_BLIT_FORMAT_RGBA_8888)
{
@@ -740,10 +753,11 @@
}
+ } /* !transform */
/* No optimized blend operation found, use default (slow) blitter. */
grub_video_fbblit_blend (target, source, x, y, width, height,
- offset_x, offset_y);
+ offset_x, offset_y, transform);
}
}
@@ -751,27 +765,34 @@
grub_video_fb_blit_bitmap (struct grub_video_bitmap *bitmap,
enum grub_video_blit_operators oper, int x, int y,
int offset_x, int offset_y,
- unsigned int width, unsigned int height)
+ int width, int height)
{
struct grub_video_fbblit_info source;
struct grub_video_fbblit_info target;
+ int src_x = offset_x;
+ int src_y = offset_y;
+
+ /* Normalize source rectangle and shift target insert point accordingly. */
+ grub_fb_norm_rect(&offset_x, &offset_y, &width, &height);
+ x += offset_x - src_x;
+ y += offset_y - src_y;
/* Make sure there is something to do. */
if ((width == 0) || (height == 0))
return GRUB_ERR_NONE;
- if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0))
+ if ((x >= render_target->viewport.width) || (x + width < 0))
return GRUB_ERR_NONE;
- if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0))
+ if ((y >= render_target->viewport.height) || (y + height < 0))
return GRUB_ERR_NONE;
if ((x + (int)bitmap->mode_info.width) < 0)
return GRUB_ERR_NONE;
if ((y + (int)bitmap->mode_info.height) < 0)
return GRUB_ERR_NONE;
if ((offset_x >= (int)bitmap->mode_info.width)
- || (offset_x + (int)width < 0))
+ || (offset_x + width < 0))
return GRUB_ERR_NONE;
if ((offset_y >= (int)bitmap->mode_info.height)
- || (offset_y + (int)height < 0))
+ || (offset_y + height < 0))
return GRUB_ERR_NONE;
/* If we have negative coordinates, optimize drawing to minimum. */
@@ -809,16 +830,16 @@
if ((y + height) > render_target->viewport.height)
height = render_target->viewport.height - y;
- if ((offset_x + width) > bitmap->mode_info.width)
+ if ((offset_x + width) > (int)bitmap->mode_info.width)
width = bitmap->mode_info.width - offset_x;
- if ((offset_y + height) > bitmap->mode_info.height)
+ if ((offset_y + height) > (int)bitmap->mode_info.height)
height = bitmap->mode_info.height - offset_y;
/* Limit drawing to source render target dimensions. */
- if (width > bitmap->mode_info.width)
+ if (width > (int)bitmap->mode_info.width)
width = bitmap->mode_info.width;
- if (height > bitmap->mode_info.height)
+ if (height > (int)bitmap->mode_info.height)
height = bitmap->mode_info.height;
/* Add viewport offset. */
@@ -842,27 +863,37 @@
grub_video_fb_blit_render_target (struct grub_video_fbrender_target *source,
enum grub_video_blit_operators oper,
int x, int y, int offset_x, int offset_y,
- unsigned int width, unsigned int height)
+ int width, int height)
{
struct grub_video_fbblit_info source_info;
struct grub_video_fbblit_info target_info;
+ int src_x = offset_x;
+ int src_y = offset_y;
+ int source_width = source->mode_info.width;
+ int source_height = source->mode_info.height;
+ fb_tran_dim_back(&source_width, &source_height, source->mode_info.transform);
+
+ /* Normalize source rectangle and shift target insert point accordingly. */
+ grub_fb_norm_rect(&offset_x, &offset_y, &width, &height);
+ x += offset_x - src_x;
+ y += offset_y - src_y;
/* Make sure there is something to do. */
if ((width == 0) || (height == 0))
return GRUB_ERR_NONE;
- if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0))
- return GRUB_ERR_NONE;
- if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0))
- return GRUB_ERR_NONE;
- if ((x + (int)source->mode_info.width) < 0)
- return GRUB_ERR_NONE;
- if ((y + (int)source->mode_info.height) < 0)
- return GRUB_ERR_NONE;
- if ((offset_x >= (int)source->mode_info.width)
- || (offset_x + (int)width < 0))
- return GRUB_ERR_NONE;
- if ((offset_y >= (int)source->mode_info.height)
- || (offset_y + (int)height < 0))
+ if ((x >= render_target->viewport.width) || (x + width < 0))
+ return GRUB_ERR_NONE;
+ if ((y >= render_target->viewport.height) || (y + height < 0))
+ return GRUB_ERR_NONE;
+ if ((x + source_width) < 0)
+ return GRUB_ERR_NONE;
+ if ((y + source_height) < 0)
+ return GRUB_ERR_NONE;
+ if ((offset_x >= source_width)
+ || (offset_x + width < 0))
+ return GRUB_ERR_NONE;
+ if ((offset_y >= source_height)
+ || (offset_y + height < 0))
return GRUB_ERR_NONE;
/* If we have negative coordinates, optimize drawing to minimum. */
@@ -900,17 +931,17 @@
if ((y + height) > render_target->viewport.height)
height = render_target->viewport.height - y;
- if ((offset_x + width) > source->mode_info.width)
- width = source->mode_info.width - offset_x;
- if ((offset_y + height) > source->mode_info.height)
- height = source->mode_info.height - offset_y;
+ if ((offset_x + width) > source_width)
+ width = source_width - offset_x;
+ if ((offset_y + height) > source_height)
+ height = source_height - offset_y;
/* Limit drawing to source render target dimensions. */
- if (width > source->mode_info.width)
- width = source->mode_info.width;
+ if (width > source_width)
+ width = source_width;
- if (height > source->mode_info.height)
- height = source->mode_info.height;
+ if (height > source_height)
+ height = source_height;
/* Add viewport offset. */
x += render_target->viewport.x;
@@ -938,6 +969,7 @@
int src_y;
int dst_x;
int dst_y;
+ int t_width, t_height;
/* 1. Check if we have something to do. */
if ((dx == 0) && (dy == 0))
@@ -968,9 +1000,16 @@
dst_y = render_target->viewport.y + dy;
}
+ t_width = width;
+ t_height = height;
+ fb_tran_rect(&src_x, &src_y, &t_width, &t_height, &render_target->mode_info);
+ t_width = width;
+ t_height = height;
+ fb_tran_rect(&dst_x, &dst_y, &t_width, &t_height, &render_target->mode_info);
+
/* 2. Check if there is need to copy data. */
- if ((grub_abs (dx) < render_target->viewport.width)
- && (grub_abs (dy) < render_target->viewport.height))
+ if (((int)grub_abs (dx) < render_target->viewport.width)
+ && ((int)grub_abs (dy) < render_target->viewport.height))
{
/* 3. Move data in render target. */
struct grub_video_fbblit_info target;
@@ -982,23 +1021,23 @@
target.data = render_target->data;
/* Check vertical direction of the move. */
- if (dy <= 0)
+ if (dst_y <= src_y)
/* 3a. Move data upwards. */
- for (j = 0; j < height; j++)
+ for (j = 0; j < t_height; j++)
{
dst = grub_video_fb_get_video_ptr (&target, dst_x, dst_y + j);
src = grub_video_fb_get_video_ptr (&target, src_x, src_y + j);
grub_memmove (dst, src,
- width * target.mode_info->bytes_per_pixel);
+ t_width * target.mode_info->bytes_per_pixel);
}
else
/* 3b. Move data downwards. */
- for (j = (height - 1); j >= 0; j--)
+ for (j = (t_height - 1); j >= 0; j--)
{
dst = grub_video_fb_get_video_ptr (&target, dst_x, dst_y + j);
src = grub_video_fb_get_video_ptr (&target, src_x, src_y + j);
grub_memmove (dst, src,
- width * target.mode_info->bytes_per_pixel);
+ t_width * target.mode_info->bytes_per_pixel);
}
}
@@ -1011,7 +1050,7 @@
grub_video_fb_fill_rect (color, 0, 0, render_target->viewport.width, dy);
else if (dy < 0)
{
- if (render_target->viewport.height < grub_abs (dy))
+ if (render_target->viewport.height < (int)grub_abs (dy))
dy = -render_target->viewport.height;
grub_video_fb_fill_rect (color, 0, render_target->viewport.height + dy,
@@ -1024,7 +1063,7 @@
dx, render_target->viewport.height);
else if (dx < 0)
{
- if (render_target->viewport.width < grub_abs (dx))
+ if (render_target->viewport.width < (int)grub_abs (dx))
dx = -render_target->viewport.width;
grub_video_fb_fill_rect (color, render_target->viewport.width + dx, 0,
@@ -1042,6 +1081,7 @@
{
struct grub_video_fbrender_target *target;
unsigned int size;
+ int transform = render_target->mode_info.transform;
/* Validate arguments. */
if ((! result)
@@ -1067,7 +1107,12 @@
target->viewport.width = width;
target->viewport.height = height;
+ /* Set up the target so that it has the same direction as the current target */
+ /* TODO: Implement other directions, too */
+ fb_tran_dim(&width, &height, transform);
+
/* Setup render target format. */
+ target->mode_info.transform = transform;
target->mode_info.width = width;
target->mode_info.height = height;
target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB
@@ -1132,10 +1177,11 @@
target->viewport.y = 0;
target->viewport.width = mode_info->width;
target->viewport.height = mode_info->height;
+ fb_tran_dim_back(&(target->viewport.width), &(target->viewport.height), mode_info->transform);
/* Clear render target with black and maximum transparency. */
for (y = 0; y < mode_info->height; y++)
- grub_memset (target->data + mode_info->pitch * y, 0,
+ grub_memset ((char *)target->data + mode_info->pitch * y, 0,
mode_info->bytes_per_pixel * mode_info->width);
/* Save result to caller. */
=== modified file 'video/i386/pc/vbe.c'
--- video/i386/pc/vbe.c 2010-01-17 16:52:01 +0000
+++ video/i386/pc/vbe.c 2010-01-19 01:07:06 +0000
@@ -355,7 +355,8 @@
status = grub_vbe_bios_set_mode (initial_vbe_mode, 0);
if (status != GRUB_VBE_STATUS_OK)
/* TODO: Decide, is this something we want to do. */
- return grub_errno;
+ return grub_error(GRUB_ERR_BAD_DEVICE,
+ "cannot reset to initial VBE mode %x", initial_vbe_mode);
last_set_mode = initial_vbe_mode;
/* TODO: Free any resources allocated by driver. */
@@ -369,7 +370,8 @@
static grub_err_t
grub_video_vbe_setup (unsigned int width, unsigned int height,
- unsigned int mode_type, unsigned int mode_mask)
+ unsigned int mode_type, unsigned int mode_mask,
+ int transform)
{
grub_uint16_t *p;
struct grub_vbe_mode_info_block vbe_mode_info;
@@ -491,6 +493,8 @@
framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info);
+ framebuffer.mode_info.transform = transform;
+
err = grub_video_fb_create_render_target_from_pointer (&framebuffer.render_target, &framebuffer.mode_info, framebuffer.ptr);
if (err)
=== modified file 'video/video.c'
--- video/video.c 2010-01-17 16:52:01 +0000
+++ video/video.c 2010-01-19 01:19:47 +0000
@@ -21,6 +21,7 @@
#include <grub/dl.h>
#include <grub/misc.h>
#include <grub/mm.h>
+#include <grub/fbtran.h>
/* The list of video adapters registered to system. */
static grub_video_adapter_t grub_video_adapter_list;
@@ -235,8 +236,7 @@
/* Set viewport dimensions. */
grub_err_t
-grub_video_set_viewport (unsigned int x, unsigned int y,
- unsigned int width, unsigned int height)
+grub_video_set_viewport (int x, int y, int width, int height)
{
if (! grub_video_adapter_active)
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
@@ -246,8 +246,7 @@
/* Get viewport dimensions. */
grub_err_t
-grub_video_get_viewport (unsigned int *x, unsigned int *y,
- unsigned int *width, unsigned int *height)
+grub_video_get_viewport (int *x, int *y, int *width, int *height)
{
if (! grub_video_adapter_active)
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
@@ -305,7 +304,7 @@
/* Fill rectangle using specified color. */
grub_err_t
grub_video_fill_rect (grub_video_color_t color, int x, int y,
- unsigned int width, unsigned int height)
+ int width, int height)
{
if (! grub_video_adapter_active)
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
@@ -318,7 +317,7 @@
grub_video_blit_bitmap (struct grub_video_bitmap *bitmap,
enum grub_video_blit_operators oper,
int x, int y, int offset_x, int offset_y,
- unsigned int width, unsigned int height)
+ int width, int height)
{
if (! grub_video_adapter_active)
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
@@ -333,7 +332,7 @@
grub_video_blit_render_target (struct grub_video_render_target *target,
enum grub_video_blit_operators oper,
int x, int y, int offset_x, int offset_y,
- unsigned int width, unsigned int height)
+ int width, int height)
{
if (! grub_video_adapter_active)
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
@@ -409,11 +408,15 @@
/* Parse <width>x<height>[x<depth>]*/
static grub_err_t
-parse_modespec (const char *current_mode, int *width, int *height, int *depth)
+parse_modespec (const char *current_mode, int *width, int *height, int *depth, int* transform)
{
const char *value;
const char *param = current_mode;
+ int flip = 0;
+ int mirror = 0;
+ int swap = 0;
+ *transform = 0;
*width = *height = *depth = -1;
if (grub_strcmp (param, "auto") == 0)
@@ -422,6 +425,36 @@
return GRUB_ERR_NONE;
}
+ /* TODO: document direction */
+ /* Parse [Dir]<width>x<height>[x<depth>]*/
+ for (;;param++)
+ switch (*param) {
+ case 'N':
+ case 'n': *transform = 0;
+ break;
+ case 'E':
+ case 'e': *transform = FB_TRAN_EAST;
+ break;
+ case 'S':
+ case 's': *transform = FB_TRAN_SOUTH;
+ break;
+ case 'W':
+ case 'w': *transform = FB_TRAN_WEST;
+ break;
+ case 'M':
+ case 'm': mirror = 1; break;
+ case 'F':
+ case 'f': flip = 1; break;
+ case 'X':
+ case 'x': swap = 1; break;
+ default: goto end_direction_parse_loop;
+ }
+end_direction_parse_loop:
+
+ if (mirror) *transform ^= FB_TRAN_MIRROR;
+ if (flip) *transform ^= FB_TRAN_FLIP;
+ if (swap) *transform ^= FB_TRAN_SWAP;
+
/* Find width value. */
value = param;
param = grub_strchr(param, 'x');
@@ -553,6 +586,7 @@
int width = -1;
int height = -1;
int depth = -1;
+ int transform = 0;
grub_err_t err;
unsigned int flags = modevalue;
unsigned int flagmask = modemask;
@@ -600,7 +634,7 @@
}
}
- err = parse_modespec (current_mode, &width, &height, &depth);
+ err = parse_modespec (current_mode, &width, &height, &depth, &transform);
if (err)
{
/* Free memory before returning. */
@@ -645,7 +679,7 @@
}
/* Try to initialize video mode. */
- err = p->setup (width, height, flags, flagmask);
+ err = p->setup (width, height, flags, flagmask, transform);
if (err != GRUB_ERR_NONE)
{
p->fini ();
# Begin bundle
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
k4KLCbf9rQ06KP+gu5IpwoSBISuLmA==
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: fb rotation merge directive
2010-01-19 1:57 fb rotation merge directive Michal Suchanek
@ 2010-01-19 11:07 ` Colin Watson
2010-01-19 11:20 ` Colin Watson
0 siblings, 1 reply; 5+ messages in thread
From: Colin Watson @ 2010-01-19 11:07 UTC (permalink / raw)
To: The development of GNU GRUB
On Tue, Jan 19, 2010 at 02:57:00AM +0100, Michal Suchanek wrote:
> As the patches were against r1782 and unlike git the bzr workflow does
> not seem to offer a rebase this is probably as good as the format
> gets.
https://launchpad.net/bzr-rewrite
As with git, it's unwise to use it on branches that have already been
published, but it's fine to use it for private patch submission
branches. (Otherwise, you can just use 'bzr merge', of course.)
--
Colin Watson [cjwatson@ubuntu.com]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: fb rotation merge directive
2010-01-19 11:07 ` Colin Watson
@ 2010-01-19 11:20 ` Colin Watson
2010-01-19 11:44 ` Michal Suchanek
0 siblings, 1 reply; 5+ messages in thread
From: Colin Watson @ 2010-01-19 11:20 UTC (permalink / raw)
To: The development of GNU GRUB
On Tue, Jan 19, 2010 at 11:07:53AM +0000, Colin Watson wrote:
> https://launchpad.net/bzr-rewrite
The lp:bzr-rewrite link is pretty stale, BTW; I think
lp:~jelmer/bzr-rewrite/trunk-mirrorred is the one you actually want (or
you can use the tarball).
--
Colin Watson [cjwatson@ubuntu.com]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: fb rotation merge directive
2010-01-19 11:20 ` Colin Watson
@ 2010-01-19 11:44 ` Michal Suchanek
2010-01-19 11:53 ` Colin Watson
0 siblings, 1 reply; 5+ messages in thread
From: Michal Suchanek @ 2010-01-19 11:44 UTC (permalink / raw)
To: The development of GNU GRUB
2010/1/19 Colin Watson <cjwatson@ubuntu.com>:
> On Tue, Jan 19, 2010 at 11:07:53AM +0000, Colin Watson wrote:
>> https://launchpad.net/bzr-rewrite
>
> The lp:bzr-rewrite link is pretty stale, BTW; I think
It has 0.5.4 which is also in Debian.
> lp:~jelmer/bzr-rewrite/trunk-mirrorred is the one you actually want (or
> you can use the tarball).
>
Either does nothing. Perhaps they don't support rebasing of branches
which are already merged with trunk.
Thanks
Michal
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: fb rotation merge directive
2010-01-19 11:44 ` Michal Suchanek
@ 2010-01-19 11:53 ` Colin Watson
0 siblings, 0 replies; 5+ messages in thread
From: Colin Watson @ 2010-01-19 11:53 UTC (permalink / raw)
To: The development of GNU GRUB
On Tue, Jan 19, 2010 at 12:44:18PM +0100, Michal Suchanek wrote:
> 2010/1/19 Colin Watson <cjwatson@ubuntu.com>:
> > lp:~jelmer/bzr-rewrite/trunk-mirrorred is the one you actually want (or
> > you can use the tarball).
>
> Either does nothing. Perhaps they don't support rebasing of branches
> which are already merged with trunk.
You could always experiment by checking out an older revision of your
branch.
In any case, there's nothing intrinsically wrong with merging in
branches that themselves have merge history. We do this ourselves quite
frequently; see the recent savedefault merge, for example.
--
Colin Watson [cjwatson@ubuntu.com]
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2010-01-19 11:53 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-01-19 1:57 fb rotation merge directive Michal Suchanek
2010-01-19 11:07 ` Colin Watson
2010-01-19 11:20 ` Colin Watson
2010-01-19 11:44 ` Michal Suchanek
2010-01-19 11:53 ` Colin Watson
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.