* [RFC,resend] framebuffer rotation patch
@ 2010-02-18 19:20 Michal Suchanek
2010-02-20 10:41 ` Vladimir 'φ-coder/phcoder' Serbinenko
0 siblings, 1 reply; 3+ messages in thread
From: Michal Suchanek @ 2010-02-18 19:20 UTC (permalink / raw)
To: The development of GRUB 2
[-- Attachment #1: Type: text/plain, Size: 704 bytes --]
Hello,
this is a framebuffer rotation patch rebased on top of current trunk.
Between the trunk commits and the actual rotation there are a few
fixes from my local branch most of which can be separated but the
scroll fix conflicts with the rotation patch.
This works for me (including terminal scrolling) in qemu and I
compile-tested earlier version for efi as well. Only videotest and
gfxterm was tested.
Most of the suggestions I got in the previous discussion are
incorporated in the new patch.
The rotation constants are declared as enum but the enum type is not
used because it would cause cyclic dependency between struct mode_info
in video.h and the transform enum in fbtrant.h
Thanks
Michal
[-- Attachment #2: fbrot.send.txt --]
[-- Type: text/plain, Size: 82369 bytes --]
# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: hramrach@heretic-20100217234249-pgpsn7vjz1fethe3
# target_branch: file:///scratch/grub2-bzr/trunk/
# testament_sha1: 8415728ce2329e5fd5f014c5bbfc5e69eb9ceed2
# timestamp: 2010-02-18 00:45:55 +0100
# base_revision_id: phcoder@gmail.com-20100216122308-9zef2mbwxt00j9ks
#
# Begin patch
=== added file 'commands/leaf.xbm'
--- commands/leaf.xbm 1970-01-01 00:00:00 +0000
+++ commands/leaf.xbm 2010-02-17 23:42:49 +0000
@@ -0,0 +1,14 @@
+#define leaf_width 32
+#define leaf_height 32
+static unsigned char leaf_bits[] = {
+ 0x00, 0xf0, 0x07, 0x00, 0x00, 0xfe, 0x3f, 0x00, 0x80, 0xff, 0xff, 0x00,
+ 0xc0, 0xff, 0xff, 0x01, 0xe0, 0xff, 0xff, 0x07, 0xf0, 0xff, 0xff, 0x0f,
+ 0xf8, 0xff, 0xff, 0x0f, 0xfc, 0xff, 0xff, 0x1f, 0xfc, 0xff, 0xff, 0x1f,
+ 0xfe, 0xff, 0xff, 0x3f, 0xfe, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0x7f,
+ 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f,
+ 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f,
+ 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x7f, 0xff, 0xff, 0xff, 0x3f,
+ 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0x1f, 0xff, 0xff, 0xff, 0x1f,
+ 0xff, 0xff, 0xff, 0x0f, 0xff, 0xff, 0xff, 0x07, 0xff, 0xff, 0xff, 0x03,
+ 0xff, 0xff, 0xff, 0x01, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0x3f, 0x00,
+ 0xff, 0xff, 0x07, 0x00, 0xff, 0x00, 0x00, 0x00 };
=== modified file 'commands/videotest.c'
--- commands/videotest.c 2010-02-16 12:23:08 +0000
+++ commands/videotest.c 2010-02-17 23:42:49 +0000
@@ -25,6 +25,102 @@
#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>
+#include "leaf.xbm"
+
+#if (leaf_width != leaf_height)
+#error Leaf must be a square bitmap.
+#endif
+#define LEAF_SIZE leaf_width
+
+unsigned char leaf_data[LEAF_SIZE*LEAF_SIZE];
+
+struct grub_video_bitmap leaves[4];
+
+static void init_leaves(void)
+{
+ static int initialized = 0;
+ int i,j;
+ if (initialized) return;
+
+ /* XBM bitmaps have bit order opposite to GRUB bitmaps. */
+ for (i = 0; i < LEAF_SIZE * LEAF_SIZE; i++)
+ for (j = 0 ; j < 8 ; j++)
+ leaf_data[i] |= ((leaf_bits[i] >> j) & 1) << (7 - j);
+
+ 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;
+
+ initialized = 1;
+}
+
+#define BORDER 32
+#define SCROLL_INC_1 2
+#define SCROLL_INC_2 4
+
+static void draw_leaves(void)
+{
+ int i;
+ grub_font_t sans;
+ grub_video_color_t text_color, fill_color, back_color;
+
+ sans = grub_font_get ("Unknown Regular 16");
+ text_color = grub_video_map_rgb (255, 255, 255);
+ fill_color = grub_video_map_rgba (0, 192, 0, 192);
+ back_color = grub_video_map_rgba (0, 0, 255, 255);
+
+ 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);
+ for (i = 0; i < BORDER ; i+=SCROLL_INC_1)
+ grub_video_scroll(back_color,-SCROLL_INC_1,0);
+ for (i = 0; i < BORDER ; i+=SCROLL_INC_1)
+ grub_video_scroll(back_color,0,-SCROLL_INC_1);
+ for (i = 0; i < BORDER ; i+=SCROLL_INC_2)
+ grub_video_scroll(back_color,+SCROLL_INC_2,+SCROLL_INC_2);
+ grub_video_fill_rect(fill_color, 0, 0, BORDER, BORDER);
+
+}
static grub_err_t
grub_cmd_videotest (grub_command_t cmd __attribute__ ((unused)),
@@ -33,10 +129,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 +148,55 @@
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_color_t frame = grub_video_map_rgb(255,0,0);
+ grub_video_fb_get_active_render_target(&tgt);
+
+ init_leaves();
+ grub_video_get_viewport (&x, &y, &width, &height);
+ x += BORDER; y += BORDER; width -= 2* BORDER; height -= 2* BORDER;
+ grub_video_fill_rect(frame, x-1, y-1, width+2, height+2);
+ frame = grub_video_map_rgb(0,0,0);
+ grub_video_fill_rect(frame, x, y, width, height);
+ grub_video_set_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 (y, x, 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 (y, x, 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 +262,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 2010-02-16 12:23:08 +0000
+++ font/font.c 2010-02-17 23:14:11 +0000
@@ -1062,8 +1062,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 'gfxmenu/gfxmenu.c'
--- gfxmenu/gfxmenu.c 2010-01-06 09:50:50 +0000
+++ gfxmenu/gfxmenu.c 2010-02-17 23:14:11 +0000
@@ -53,6 +53,7 @@
struct grub_menu_viewer *instance;
grub_err_t err;
struct grub_video_mode_info mode_info;
+ int screen_width, screen_height;
theme_path = grub_env_get ("theme");
if (! theme_path)
@@ -81,14 +82,16 @@
return err;
}
+ grub_video_get_max_viewport(&screen_width, &screen_height);
+
if (!cached_view || grub_strcmp (cached_view->theme_path, theme_path) != 0
- || cached_view->screen.width != mode_info.width
- || cached_view->screen.height != mode_info.height)
+ || cached_view->screen.width != (unsigned)screen_width
+ || cached_view->screen.height != (unsigned)screen_height)
{
grub_free (cached_view);
/* Create the view. */
- cached_view = grub_gfxmenu_view_new (theme_path, mode_info.width,
- mode_info.height);
+ cached_view = grub_gfxmenu_view_new (theme_path, screen_width,
+ screen_height);
}
if (! cached_view)
=== modified file 'include/grub/fbblit.h'
--- include/grub/fbblit.h 2009-08-28 13:54:20 +0000
+++ include/grub/fbblit.h 2010-02-17 23:14:11 +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-02-17 22:25:37 +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-02-17 23:14:11 +0000
@@ -0,0 +1,233 @@
+/*
+ * 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 (and also happen to
+ * form a symmetry group).
+ *
+ * MIRROR | swap image across (around) the vertical axis 1-2 2-1
+ * | | -> | |
+ * 3-4 4-3
+ * 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-inversions.
+ * || = -- = // = 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 correct
+ * picture when facing the east side of the screen we need the -\ transform.
+ *
+ * E = -rot90 = -\
+ * S = -rot180 = -\-\ = -|\\ = -|
+ * W = -rot270 = -|-\ = |\
+ *
+ * As is seen from the above every supported screen transform can be represented by
+ * applying the basic -,| and \ operations at most ance in a fixed order.
+ * Thus each supoprted transform can be represented by a three-bit bitfield specifying
+ * which basic operations should be applied.
+ *
+ * Forward transform is from user visible cordinates to framebuffer memory coordinates.
+ */
+
+typedef enum {
+ FB_TRAN_SWAP = (1 << 0),
+ FB_TRAN_FLIP = (1 << 1),
+ FB_TRAN_MIRROR = (1 << 2),
+ //FB_TRAN_MASK = 7,
+ //FB_TRAN_SIMPLE = 6,
+ FB_TRAN_NORTH = 0,
+ FB_TRAN_EAST = (FB_TRAN_FLIP | FB_TRAN_SWAP),
+ FB_TRAN_SOUTH = (FB_TRAN_FLIP | FB_TRAN_MIRROR),
+ FB_TRAN_WEST = (FB_TRAN_MIRROR | FB_TRAN_SWAP),
+} fb_trans_t;
+
+/* 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 (composition). Should work on modes that have the same
+ * width and height at the point the transfom is appended. In other words:
+ * Internal use only. */
+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. (inversion)
+ * Note: the possible operations aren't commutative but left and right
+ * inversion are the same for supported operations.*/
+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. (decomposition/factorization)
+ * Internal use only.*/
+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(*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(*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(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(*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(*x, x2);
+ (*x)++;
+ x2++;
+ }
+ if(*y > y2)
+ {
+ grub_swap(*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/gui.h'
--- include/grub/gui.h 2010-01-06 00:42:21 +0000
+++ include/grub/gui.h 2010-02-17 22:25:37 +0000
@@ -173,10 +173,10 @@
static __inline void
grub_gui_save_viewport (grub_video_rect_t *r)
{
- grub_video_get_viewport ((unsigned *) &r->x,
- (unsigned *) &r->y,
- (unsigned *) &r->width,
- (unsigned *) &r->height);
+ grub_video_get_viewport ((int *) &r->x,
+ (int *) &r->y,
+ (int *) &r->width,
+ (int *) &r->height);
}
static __inline void
=== modified file 'include/grub/misc.h'
--- include/grub/misc.h 2010-02-03 00:24:07 +0000
+++ include/grub/misc.h 2010-02-17 23:14:11 +0000
@@ -267,6 +267,8 @@
/* Inline functions. */
+#define grub_swap(a,b) {typeof (a) _tmpval ## __LINE__; _tmpval ## __LINE__ = (b); (b) = (a); (a) = _tmpval ## __LINE__; }
+
static inline unsigned int
grub_abs (int x)
{
@@ -285,6 +287,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-02-03 00:24:07 +0000
+++ include/grub/video.h 2010-02-17 23:14:11 +0000
@@ -155,6 +155,8 @@
grub_uint8_t fg_green;
grub_uint8_t fg_blue;
grub_uint8_t fg_alpha;
+
+ int transform;
};
/* A 2D rectangle type. */
@@ -196,7 +198,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);
@@ -209,11 +212,11 @@
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 (*get_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_max_viewport) (int *width, 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);
@@ -228,17 +231,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);
@@ -283,11 +286,13 @@
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_get_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_max_viewport (int *width, 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);
@@ -302,19 +307,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-11-14 16:00:39 +0000
+++ include/grub/video_fb.h 2010-02-17 23:14:11 +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,14 @@
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_err_t
-grub_video_fb_get_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_max_viewport (int *width, int *height);
+
+grub_err_t
+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 +104,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-02-03 00:24:07 +0000
+++ term/gfxterm.c 2010-02-17 23:14:11 +0000
@@ -319,6 +319,7 @@
grub_video_color_t color;
grub_err_t err;
int double_redraw;
+ int view_width, view_height;
err = grub_video_get_info (&mode_info);
/* Figure out what mode we ended up. */
@@ -329,14 +330,15 @@
double_redraw = mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
&& !(mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
+ grub_video_get_max_viewport(&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);
if (double_redraw)
{
grub_video_swap_buffers ();
- 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;
@@ -348,7 +350,7 @@
grub_gfxterm_decorator_hook = NULL;
return grub_gfxterm_set_window (GRUB_VIDEO_RENDER_TARGET_DISPLAY,
- 0, 0, mode_info.width, mode_info.height,
+ 0, 0, view_width, view_height,
double_redraw,
font_name, DEFAULT_BORDER_WIDTH);
}
@@ -417,10 +419,10 @@
grub_video_set_active_render_target (render_target);
/* Save viewport and set it to our window. */
- grub_video_get_viewport ((unsigned *) &saved_view.x,
- (unsigned *) &saved_view.y,
- (unsigned *) &saved_view.width,
- (unsigned *) &saved_view.height);
+ grub_video_get_viewport ((int *) &saved_view.x,
+ (int *) &saved_view.y,
+ (int *) &saved_view.width,
+ (int *) &saved_view.height);
grub_video_set_viewport (window.x, window.y, window.width, window.height);
if (bitmap)
@@ -707,10 +709,10 @@
grub_video_set_active_render_target (render_target);
/* Save viewport and set it to our window. */
- grub_video_get_viewport ((unsigned *) &saved_view.x,
- (unsigned *) &saved_view.y,
- (unsigned *) &saved_view.width,
- (unsigned *) &saved_view.height);
+ grub_video_get_viewport ((int *) &saved_view.x,
+ (int *) &saved_view.y,
+ (int *) &saved_view.width,
+ (int *) &saved_view.height);
grub_video_set_viewport (window.x, window.y, window.width, window.height);
i = window.double_repaint ? 2 : 1;
=== modified file 'util/grub-mkrescue.in'
--- util/grub-mkrescue.in 2009-12-22 17:20:27 +0000
+++ util/grub-mkrescue.in 2010-01-19 10:41:54 +0000
@@ -37,7 +37,7 @@
# Print the usage.
usage () {
cat <<EOF
-Usage: $0 [OPTION] SOURCE...
+Usage: $0 --output=FILE [OPTION...] [SOURCE...]
Make GRUB rescue image.
-h, --help print this message and exit
@@ -45,7 +45,9 @@
--modules=MODULES pre-load specified modules MODULES
--output=FILE save output in FILE [required]
-$0 generates a bootable rescue image with specified source files or directories.
+ $0 generates a bootable grub rescue image.
+ Additional files and directories to include in the image can be specified
+ as sources.
Report bugs to <bug-grub@gnu.org>.
EOF
=== modified file 'util/sdl.c'
--- util/sdl.c 2010-02-07 01:47:18 +0000
+++ util/sdl.c 2010-02-17 23:14:11 +0000
@@ -70,7 +70,8 @@
static grub_err_t
grub_video_sdl_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)
{
int depth;
int flags = 0;
@@ -102,6 +103,10 @@
grub_memset (&sdl_render_target, 0, sizeof (sdl_render_target));
+ /* TODO: transform the picture back before displaying in the window.
+ * Also swap width and height as required. */
+ mode_info.transform = transform;
+
mode_info.width = window->w;
mode_info.height = window->h;
mode_info.mode_type = 0;
@@ -208,6 +213,7 @@
.set_palette = grub_video_sdl_set_palette,
.get_palette = grub_video_fb_get_palette,
.set_viewport = grub_video_fb_set_viewport,
+ .get_max_viewport = grub_video_fb_get_max_viewport,
.get_viewport = grub_video_fb_get_viewport,
.map_color = grub_video_fb_map_color,
.map_rgb = grub_video_fb_map_rgb,
=== modified file 'video/bitmap.c'
--- video/bitmap.c 2009-12-24 22:53:05 +0000
+++ video/bitmap.c 2010-02-17 23:14:11 +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-02-03 00:24:07 +0000
+++ video/efi_gop.c 2010-02-17 23:14:11 +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;
@@ -288,6 +289,7 @@
return err;
}
+ framebuffer.mode_info.transform = transform;
framebuffer.ptr = (void *) (grub_addr_t) gop->mode->fb_base;
grub_dprintf ("video", "GOP: initialising FB @ %p %dx%dx%d\n",
@@ -363,6 +365,7 @@
.set_palette = grub_video_fb_set_palette,
.get_palette = grub_video_fb_get_palette,
.set_viewport = grub_video_fb_set_viewport,
+ .get_max_viewport = grub_video_fb_get_max_viewport,
.get_viewport = grub_video_fb_get_viewport,
.map_color = grub_video_fb_map_color,
.map_rgb = grub_video_fb_map_rgb,
=== modified file 'video/efi_uga.c'
--- video/efi_uga.c 2010-02-03 00:24:07 +0000
+++ video/efi_uga.c 2010-02-17 23:14:11 +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. */
@@ -310,6 +312,7 @@
.set_palette = grub_video_fb_set_palette,
.get_palette = grub_video_fb_get_palette,
.set_viewport = grub_video_fb_set_viewport,
+ .get_max_viewport = grub_video_fb_get_max_viewport,
.get_viewport = grub_video_fb_get_viewport,
.map_color = grub_video_fb_map_color,
.map_rgb = grub_video_fb_map_rgb,
=== modified file 'video/fb/fbblit.c'
--- video/fb/fbblit.c 2009-08-28 13:54:20 +0000
+++ video/fb/fbblit.c 2010-02-17 23:14:11 +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-19 20:31:47 +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-19 20:31:47 +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 2010-02-03 00:24:07 +0000
+++ video/fb/video_fb.c 2010-02-17 23:14:11 +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;
@@ -119,28 +120,37 @@
}
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)
{
- /* Make sure viewport is withing screen dimensions. If viewport was set
+ /* Make sure viewport is within 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, mode_height;
+
+ grub_video_fb_get_max_viewport (&mode_width, &mode_height);
+ grub_fb_norm_rect(&x, &y, &width, &height);
+
+ 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)
- width = render_target->mode_info.width - x;
-
- if (y + height > render_target->mode_info.height)
- height = render_target->mode_info.height - y;
+ if (x < 0) { width += x; x = 0; }
+ if (width < 0) width = 0;
+ if (y < 0) { height += y; y = 0; }
+ if (height < 0) height = 0;
+
+ if (x + width > mode_width)
+ width = mode_width - x;
+
+ if (y + height > mode_height)
+ height = mode_height - y;
render_target->viewport.x = x;
render_target->viewport.y = y;
@@ -151,8 +161,19 @@
}
grub_err_t
-grub_video_fb_get_viewport (unsigned int *x, unsigned int *y,
- unsigned int *width, unsigned int *height)
+grub_video_fb_get_max_viewport (int *width, int *height)
+{
+ unsigned mode_width = render_target->mode_info.width;
+ unsigned mode_height = render_target->mode_info.height;
+ fb_tran_dim(&mode_width, &mode_height, render_target->mode_info.transform);
+ if (width) *width = mode_width;
+ if (height) *height = mode_height;
+
+ return GRUB_ERR_NONE;
+}
+
+grub_err_t
+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;
@@ -401,14 +422,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. */
@@ -436,6 +458,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)
@@ -487,11 +512,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)
{
@@ -620,13 +649,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)
{
@@ -742,10 +773,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);
}
}
@@ -753,27 +785,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. */
@@ -811,16 +850,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. */
@@ -844,27 +883,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. */
@@ -902,17 +951,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;
@@ -940,6 +989,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))
@@ -970,9 +1020,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;
@@ -983,18 +1040,25 @@
target.data = render_target->data;
linedelta = target.mode_info->pitch
- - width * target.mode_info->bytes_per_pixel;
- linelen = width * target.mode_info->bytes_per_pixel;
+ - t_width * target.mode_info->bytes_per_pixel;
+ linelen = t_width * target.mode_info->bytes_per_pixel;
+ if (src_y < dst_y || (src_y == dst_y && src_x < dst_x))
+ {
+ src_x += t_width - 1;
+ dst_x += t_width - 1;
+ src_y += t_height - 1;
+ dst_y += t_height - 1;
+ }
#define DO_SCROLL \
/* Check vertical direction of the move. */ \
- if (dy < 0 || (dy == 0 && dx < 0)) \
+ if (src_y > dst_y || (src_y == dst_y && src_x > dst_x)) \
{ \
dst = (void *) grub_video_fb_get_video_ptr (&target, \
dst_x, dst_y); \
src = (void *) grub_video_fb_get_video_ptr (&target, \
src_x, src_y); \
/* 3a. Move data upwards. */ \
- for (j = 0; j < height; j++) \
+ for (j = 0; j < t_height; j++) \
{ \
for (i = 0; i < linelen; i++) \
*(dst++) = *(src++); \
@@ -1006,12 +1070,10 @@
{ \
/* 3b. Move data downwards. */ \
dst = (void *) grub_video_fb_get_video_ptr (&target, \
- dst_x + width - 1, \
- dst_y + height - 1); \
+ dst_x, dst_y); \
src = (void *) grub_video_fb_get_video_ptr (&target, \
- src_x + width - 1, \
- src_y + height - 1); \
- for (j = 0; j < height; j++) \
+ src_x, src_y); \
+ for (j = 0; j < t_height; j++) \
{ \
for (i = 0; i < linelen; i++) \
*(dst--) = *(src--); \
@@ -1052,7 +1114,7 @@
{
grub_uint8_t *src, *dst;
DO_SCROLL
- }
+ }
}
/* 4. Fill empty space with specified color. In this implementation
@@ -1064,7 +1126,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,
@@ -1077,7 +1139,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,
@@ -1095,6 +1157,7 @@
{
struct grub_video_fbrender_target *target;
unsigned int size;
+ int transform = render_target->mode_info.transform;
/* Validate arguments. */
if ((! result)
@@ -1120,7 +1183,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
@@ -1185,10 +1253,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-02-03 00:24:07 +0000
+++ video/i386/pc/vbe.c 2010-02-17 23:14:11 +0000
@@ -368,7 +368,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. */
@@ -561,7 +562,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;
@@ -681,6 +683,8 @@
framebuffer.mode_info.reserved_mask_size = active_vbe_mode_info.rsvd_mask_size;
framebuffer.mode_info.reserved_field_pos = active_vbe_mode_info.rsvd_field_position;
+ framebuffer.mode_info.transform = transform;
+
framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info);
/* Set up double buffering and targets. */
@@ -790,6 +794,7 @@
.set_palette = grub_video_vbe_set_palette,
.get_palette = grub_video_fb_get_palette,
.set_viewport = grub_video_fb_set_viewport,
+ .get_max_viewport = grub_video_fb_get_max_viewport,
.get_viewport = grub_video_fb_get_viewport,
.map_color = grub_video_fb_map_color,
.map_rgb = grub_video_fb_map_rgb,
=== modified file 'video/sm712.c'
--- video/sm712.c 2010-01-20 19:49:18 +0000
+++ video/sm712.c 2010-02-17 23:14:11 +0000
@@ -62,7 +62,8 @@
static grub_err_t
grub_video_sm712_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)
{
int depth;
grub_err_t err;
@@ -108,6 +109,7 @@
}
/* Fill mode info details. */
+ framebuffer.mode_info.transform = transform;
framebuffer.mode_info.width = 1024;
framebuffer.mode_info.height = 600;
framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB;
@@ -200,6 +202,7 @@
.set_palette = grub_video_sm712_set_palette,
.get_palette = grub_video_fb_get_palette,
.set_viewport = grub_video_fb_set_viewport,
+ .get_max_viewport = grub_video_fb_get_max_viewport,
.get_viewport = grub_video_fb_get_viewport,
.map_color = grub_video_fb_map_color,
.map_rgb = grub_video_fb_map_rgb,
=== modified file 'video/video.c'
--- video/video.c 2010-02-03 00:24:07 +0000
+++ video/video.c 2010-02-17 23:14:11 +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;
@@ -233,10 +234,9 @@
return grub_video_adapter_active->get_palette (start, count, palette_data);
}
-/* Set viewport dimensions. */
+/* Set viewport. */
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");
@@ -244,10 +244,19 @@
return grub_video_adapter_active->set_viewport (x, y, width, height);
}
-/* Get viewport dimensions. */
-grub_err_t
-grub_video_get_viewport (unsigned int *x, unsigned int *y,
- unsigned int *width, unsigned int *height)
+/* Get maximum viewport dimensions. */
+grub_err_t
+grub_video_get_max_viewport (int *width, int *height)
+{
+ if (! grub_video_adapter_active)
+ return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
+
+ return grub_video_adapter_active->get_max_viewport (width, height);
+}
+
+/* Get viewport. */
+grub_err_t
+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 +314,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 +327,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 +342,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 +418,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 +435,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 +596,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 +644,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 +689,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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
YqwPpeLkKXQhsZh+wXckU4UJBiER5UA=
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [RFC,resend] framebuffer rotation patch
2010-02-18 19:20 [RFC,resend] framebuffer rotation patch Michal Suchanek
@ 2010-02-20 10:41 ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-02-21 12:28 ` Michal Suchanek
0 siblings, 1 reply; 3+ messages in thread
From: Vladimir 'φ-coder/phcoder' Serbinenko @ 2010-02-20 10:41 UTC (permalink / raw)
To: The development of GNU GRUB
[-- Attachment #1: Type: text/plain, Size: 1268 bytes --]
Michal Suchanek wrote:
> Hello,
>
> this is a framebuffer rotation patch rebased on top of current trunk.
> Between the trunk commits and the actual rotation there are a few
> fixes from my local branch most of which can be separated but the
> scroll fix conflicts with the rotation patch.
>
> This works for me (including terminal scrolling) in qemu and I
> compile-tested earlier version for efi as well. Only videotest and
> gfxterm was tested.
>
> Most of the suggestions I got in the previous discussion are
> incorporated in the new patch.
>
You have included some unrelated changes in your patch like useless
grub-mkrescue.in change.
What is the reason for get_max_viewport function? Why not just transform
mode_info?
> The rotation constants are declared as enum but the enum type is not
> used because it would cause cyclic dependency between struct mode_info
> in video.h and the transform enum in fbtrant.h
>
> Thanks
>
> Michal
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> http://lists.gnu.org/mailman/listinfo/grub-devel
--
Regards
Vladimir 'φ-coder/phcoder' Serbinenko
[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 293 bytes --]
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [RFC,resend] framebuffer rotation patch
2010-02-20 10:41 ` Vladimir 'φ-coder/phcoder' Serbinenko
@ 2010-02-21 12:28 ` Michal Suchanek
0 siblings, 0 replies; 3+ messages in thread
From: Michal Suchanek @ 2010-02-21 12:28 UTC (permalink / raw)
To: The development of GNU GRUB
2010/2/20 Vladimir 'φ-coder/phcoder' Serbinenko <phcoder@gmail.com>:
> Michal Suchanek wrote:
>> Hello,
>>
>> this is a framebuffer rotation patch rebased on top of current trunk.
>> Between the trunk commits and the actual rotation there are a few
>> fixes from my local branch most of which can be separated but the
>> scroll fix conflicts with the rotation patch.
>>
>> This works for me (including terminal scrolling) in qemu and I
>> compile-tested earlier version for efi as well. Only videotest and
>> gfxterm was tested.
>>
>> Most of the suggestions I got in the previous discussion are
>> incorporated in the new patch.
>>
> You have included some unrelated changes in your patch like useless
> grub-mkrescue.in change.
Yes, they are included as separate changesets, though.
> What is the reason for get_max_viewport function? Why not just transform
> mode_info?
Because get_max_viewport is a user function. Transforming mode_info in
every code using framebuffer would be error-prone, the users of the fb
code should not need to invoke the transform functions.
In the current users of get_max_viewport you can get away with
get_veiwport (and throwing away the first two values) because all such
uses happen just after graphics mode initialization and the current
viewport is the maximum one. This might not be always the case in the
future, though.
Thanks
Michal
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2010-02-21 12:28 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-02-18 19:20 [RFC,resend] framebuffer rotation patch Michal Suchanek
2010-02-20 10:41 ` Vladimir 'φ-coder/phcoder' Serbinenko
2010-02-21 12:28 ` Michal Suchanek
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.