Cirrus 5446 and Bochs video cards support.
* conf/i386.rmk (pkglib_MODULES): Add video_cirrus.mod and video_bochs.mod (video_cirrus_mod_SOURCES): New variable. (video_cirrus_mod_CFLAGS): Likewise. (video_cirrus_mod_LDFLAGS): Likewise. (video_bochs_mod_SOURCES): Likewise. (video_bochs_mod_CFLAGS): Likewise. (video_bochs_mod_LDFLAGS): Likewise. * include/grub/vga.h: New file. * include/grub/video_fb.h (grub_video_fb_doublebuf_blit_init): Removed. (grub_video_fb_set_page_t): New type. (grub_video_fb_setup): New prototype. (grub_video_fb_swap_buffers): Likewise. (grub_video_fb_get_info_and_fini): Likewise. * term/i386/pc/vga_text.c (CRTC_ADDR_PORT): Moved to include/grub/vga.h. (CRTC_DATA_PORT): Likewise. (CRTC_CURSOR): Likewise. (CRTC_CURSOR_ADDR_HIGH): Likewise. (CRTC_CURSOR_ADDR_LOW): Likewise. (CRTC_CURSOR_DISABLE): Likewise. (update_cursor): Use grub_vga_cr_write. (grub_vga_text_setcursor): Likewise. * video/bochs.c: New file. * video/fb/video_fb.c (render_target): Moved into framebuffer variable. (palette): Likewise. (palette_size): Likewise. (framebuffer): New variable. (grub_video_fb_init): Use 'framebuffer'. (grub_video_fb_fini): Likewise. (grub_video_fb_get_info): Likewise. (grub_video_fb_get_palette): Likewise. (grub_video_fb_set_palette): Likewise. (grub_video_fb_set_viewport): Likewise. (grub_video_fb_get_viewport): Likewise. (grub_video_fb_map_color): Likewise. (grub_video_fb_map_rgb): Likewise. (grub_video_fb_map_rgba): Likewise. (grub_video_fb_unmap_color): Likewise. (grub_video_fb_unmap_color_int): Likewise. (grub_video_fb_fill_rect): Likewise. (grub_video_fb_blit_bitmap): Likewise. (grub_video_fb_blit_render_target): Likewise. (grub_video_fb_scroll): Likewise. (grub_video_fb_create_render_target): Likewise. (grub_video_fb_doublebuf_blit_init): Likewise. (grub_video_fb_set_active_render_target): Handle doublebuffering. (doublebuf_pageflipping_update_screen): New function. (doublebuf_pageflipping_init): Likewise. (grub_video_fb_setup): Likewise. (grub_video_fb_swap_buffers): Likewise. (grub_video_fb_get_info_and_fini): Likewise. * video/i386/pc/vbe.c (framebuffer): Remove all doublebuffering fields. All users updated. (doublebuf_pageflipping_commit): Restructured into ... (doublebuf_pageflipping_set_page): ... this. (doublebuf_pageflipping_update_screen): Removed. (doublebuf_pageflipping_init): Likewise. (double_buffering_init): Likewise. (grub_video_vbe_setup): Use grub_video_fb_setup. (grub_video_vbe_swap_buffers): Removed. (grub_video_vbe_set_active_render_target): Likewise. (grub_video_vbe_get_active_render_target): Likewise. (grub_video_vbe_get_info_and_fini): Use grub_video_fb_get_info_and_fini. (grub_video_vbe_adapter): Use grub_video_fb_swap_buffers, grub_video_fb_set_active_render_target and grub_video_fb_get_active_render_target. * video/i386/pc/vga.c (SEQUENCER_ADDR_PORT): Move to include/grub/vga.h. (SEQUENCER_DATA_PORT): Likewise. (MAP_MASK_REGISTER): Likewise. (CRTC_ADDR_PORT): Likewise. (CRTC_DATA_PORT): Likewise. (START_ADDR_HIGH_REGISTER): Likewise. (START_ADDR_LOW_REGISTER): Likewise. (GRAPHICS_ADDR_PORT): Likewise. (GRAPHICS_DATA_PORT): Likewise. (READ_MAP_REGISTER): Likewise. (INPUT_STATUS1_REGISTER): Likewise. (INPUT_STATUS1_VERTR_BIT): Likewise. (get_map_mask): Use grub_vga_sr_read. (set_map_mask): Use grub_vga_sr_write. (set_read_map): Use grub_vga_gr_write. (set_start_address): Use grub_vga_cr_write. * video/sm712.c (framebuffer): Remove leftover fields.
This commit is contained in:
commit
05e5187978
12 changed files with 1619 additions and 454 deletions
88
ChangeLog
88
ChangeLog
|
@ -1,3 +1,91 @@
|
|||
2010-06-20 Vladimir Serbinenko <phcoder@gmail.com>
|
||||
|
||||
Cirrus 5446 and Bochs video cards support.
|
||||
|
||||
* conf/i386.rmk (pkglib_MODULES): Add video_cirrus.mod and
|
||||
video_bochs.mod
|
||||
(video_cirrus_mod_SOURCES): New variable.
|
||||
(video_cirrus_mod_CFLAGS): Likewise.
|
||||
(video_cirrus_mod_LDFLAGS): Likewise.
|
||||
(video_bochs_mod_SOURCES): Likewise.
|
||||
(video_bochs_mod_CFLAGS): Likewise.
|
||||
(video_bochs_mod_LDFLAGS): Likewise.
|
||||
* include/grub/vga.h: New file.
|
||||
* include/grub/video_fb.h (grub_video_fb_doublebuf_blit_init): Removed.
|
||||
(grub_video_fb_set_page_t): New type.
|
||||
(grub_video_fb_setup): New prototype.
|
||||
(grub_video_fb_swap_buffers): Likewise.
|
||||
(grub_video_fb_get_info_and_fini): Likewise.
|
||||
* term/i386/pc/vga_text.c (CRTC_ADDR_PORT): Moved to include/grub/vga.h.
|
||||
(CRTC_DATA_PORT): Likewise.
|
||||
(CRTC_CURSOR): Likewise.
|
||||
(CRTC_CURSOR_ADDR_HIGH): Likewise.
|
||||
(CRTC_CURSOR_ADDR_LOW): Likewise.
|
||||
(CRTC_CURSOR_DISABLE): Likewise.
|
||||
(update_cursor): Use grub_vga_cr_write.
|
||||
(grub_vga_text_setcursor): Likewise.
|
||||
* video/bochs.c: New file.
|
||||
* video/fb/video_fb.c (render_target): Moved into framebuffer variable.
|
||||
(palette): Likewise.
|
||||
(palette_size): Likewise.
|
||||
(framebuffer): New variable.
|
||||
(grub_video_fb_init): Use 'framebuffer'.
|
||||
(grub_video_fb_fini): Likewise.
|
||||
(grub_video_fb_get_info): Likewise.
|
||||
(grub_video_fb_get_palette): Likewise.
|
||||
(grub_video_fb_set_palette): Likewise.
|
||||
(grub_video_fb_set_viewport): Likewise.
|
||||
(grub_video_fb_get_viewport): Likewise.
|
||||
(grub_video_fb_map_color): Likewise.
|
||||
(grub_video_fb_map_rgb): Likewise.
|
||||
(grub_video_fb_map_rgba): Likewise.
|
||||
(grub_video_fb_unmap_color): Likewise.
|
||||
(grub_video_fb_unmap_color_int): Likewise.
|
||||
(grub_video_fb_fill_rect): Likewise.
|
||||
(grub_video_fb_blit_bitmap): Likewise.
|
||||
(grub_video_fb_blit_render_target): Likewise.
|
||||
(grub_video_fb_scroll): Likewise.
|
||||
(grub_video_fb_create_render_target): Likewise.
|
||||
(grub_video_fb_doublebuf_blit_init): Likewise.
|
||||
(grub_video_fb_set_active_render_target): Handle doublebuffering.
|
||||
(doublebuf_pageflipping_update_screen): New function.
|
||||
(doublebuf_pageflipping_init): Likewise.
|
||||
(grub_video_fb_setup): Likewise.
|
||||
(grub_video_fb_swap_buffers): Likewise.
|
||||
(grub_video_fb_get_info_and_fini): Likewise.
|
||||
* video/i386/pc/vbe.c (framebuffer): Remove all doublebuffering fields.
|
||||
All users updated.
|
||||
(doublebuf_pageflipping_commit): Restructured into ...
|
||||
(doublebuf_pageflipping_set_page): ... this.
|
||||
(doublebuf_pageflipping_update_screen): Removed.
|
||||
(doublebuf_pageflipping_init): Likewise.
|
||||
(double_buffering_init): Likewise.
|
||||
(grub_video_vbe_setup): Use grub_video_fb_setup.
|
||||
(grub_video_vbe_swap_buffers): Removed.
|
||||
(grub_video_vbe_set_active_render_target): Likewise.
|
||||
(grub_video_vbe_get_active_render_target): Likewise.
|
||||
(grub_video_vbe_get_info_and_fini): Use grub_video_fb_get_info_and_fini.
|
||||
(grub_video_vbe_adapter): Use grub_video_fb_swap_buffers,
|
||||
grub_video_fb_set_active_render_target and
|
||||
grub_video_fb_get_active_render_target.
|
||||
* video/i386/pc/vga.c (SEQUENCER_ADDR_PORT): Move to include/grub/vga.h.
|
||||
(SEQUENCER_DATA_PORT): Likewise.
|
||||
(MAP_MASK_REGISTER): Likewise.
|
||||
(CRTC_ADDR_PORT): Likewise.
|
||||
(CRTC_DATA_PORT): Likewise.
|
||||
(START_ADDR_HIGH_REGISTER): Likewise.
|
||||
(START_ADDR_LOW_REGISTER): Likewise.
|
||||
(GRAPHICS_ADDR_PORT): Likewise.
|
||||
(GRAPHICS_DATA_PORT): Likewise.
|
||||
(READ_MAP_REGISTER): Likewise.
|
||||
(INPUT_STATUS1_REGISTER): Likewise.
|
||||
(INPUT_STATUS1_VERTR_BIT): Likewise.
|
||||
(get_map_mask): Use grub_vga_sr_read.
|
||||
(set_map_mask): Use grub_vga_sr_write.
|
||||
(set_read_map): Use grub_vga_gr_write.
|
||||
(set_start_address): Use grub_vga_cr_write.
|
||||
* video/sm712.c (framebuffer): Remove leftover fields.
|
||||
|
||||
2010-06-20 Colin Watson <cjwatson@ubuntu.com>
|
||||
|
||||
* util/grub-mkconfig.in: Capitalise and export GRUB_PREFIX. Stop
|
||||
|
|
|
@ -15,6 +15,16 @@ vga_text_mod_SOURCES = term/i386/pc/vga_text.c term/i386/vga_common.c
|
|||
vga_text_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||
vga_text_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||
|
||||
pkglib_MODULES += video_cirrus.mod
|
||||
video_cirrus_mod_SOURCES = video/cirrus.c
|
||||
video_cirrus_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||
video_cirrus_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||
|
||||
pkglib_MODULES += video_bochs.mod
|
||||
video_bochs_mod_SOURCES = video/bochs.c
|
||||
video_bochs_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||
video_bochs_mod_LDFLAGS = $(COMMON_LDFLAGS)
|
||||
|
||||
pkglib_MODULES += relocator.mod
|
||||
relocator_mod_SOURCES = lib/i386/relocator.c lib/i386/relocator_asm.S lib/i386/relocator_backward.S
|
||||
relocator_mod_CFLAGS = $(COMMON_CFLAGS)
|
||||
|
|
161
include/grub/vga.h
Normal file
161
include/grub/vga.h
Normal file
|
@ -0,0 +1,161 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2010 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_VGA_HEADER
|
||||
#define GRUB_VGA_HEADER 1
|
||||
|
||||
enum
|
||||
{
|
||||
GRUB_VGA_IO_SR_INDEX = 0x3c4,
|
||||
GRUB_VGA_IO_SR_DATA = 0x3c5,
|
||||
GRUB_VGA_IO_PIXEL_MASK = 0x3c6,
|
||||
GRUB_VGA_IO_PALLETTE_READ_INDEX = 0x3c7,
|
||||
GRUB_VGA_IO_PALLETTE_WRITE_INDEX = 0x3c8,
|
||||
GRUB_VGA_IO_PALLETTE_DATA = 0x3c9,
|
||||
GRUB_VGA_IO_GR_INDEX = 0x3ce,
|
||||
GRUB_VGA_IO_GR_DATA = 0x3cf,
|
||||
GRUB_VGA_IO_CR_INDEX = 0x3d4,
|
||||
GRUB_VGA_IO_CR_DATA = 0x3d5,
|
||||
GRUB_VGA_IO_INPUT_STATUS1_REGISTER = 0x3da
|
||||
};
|
||||
|
||||
#define GRUB_VGA_IO_INPUT_STATUS1_VERTR_BIT 0x08
|
||||
|
||||
enum
|
||||
{
|
||||
GRUB_VGA_CR_WIDTH = 0x01,
|
||||
GRUB_VGA_CR_OVERFLOW = 0x07,
|
||||
GRUB_VGA_CR_CELL_HEIGHT = 0x09,
|
||||
GRUB_VGA_CR_CURSOR = 0x0a,
|
||||
GRUB_VGA_CR_START_ADDR_HIGH_REGISTER = 0x0c,
|
||||
GRUB_VGA_CR_START_ADDR_LOW_REGISTER = 0x0d,
|
||||
GRUB_VGA_CR_CURSOR_ADDR_HIGH = 0x0e,
|
||||
GRUB_VGA_CR_CURSOR_ADDR_LOW = 0x0f,
|
||||
GRUB_VGA_CR_VSYNC_END = 0x11,
|
||||
GRUB_VGA_CR_HEIGHT = 0x12,
|
||||
GRUB_VGA_CR_PITCH = 0x13,
|
||||
GRUB_VGA_CR_MODE = 0x17,
|
||||
GRUB_VGA_CR_LINE_COMPARE = 0x18,
|
||||
};
|
||||
|
||||
#define GRUB_VGA_CR_WIDTH_DIVISOR 8
|
||||
#define GRUB_VGA_CR_OVERFLOW_HEIGHT1_SHIFT 7
|
||||
#define GRUB_VGA_CR_OVERFLOW_HEIGHT1_MASK 0x02
|
||||
#define GRUB_VGA_CR_OVERFLOW_HEIGHT2_SHIFT 3
|
||||
#define GRUB_VGA_CR_OVERFLOW_HEIGHT2_MASK 0xc0
|
||||
#define GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_SHIFT 4
|
||||
#define GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_MASK 0x10
|
||||
|
||||
#define GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_MASK 0x40
|
||||
#define GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT 3
|
||||
|
||||
#define GRUB_VGA_CR_CURSOR_DISABLE (1 << 5)
|
||||
|
||||
#define GRUB_VGA_CR_PITCH_DIVISOR 8
|
||||
|
||||
#define GRUB_VGA_CR_MODE_TIMING_ENABLE 0x80
|
||||
#define GRUB_VGA_CR_MODE_BYTE_MODE 0x40
|
||||
#define GRUB_VGA_CR_MODE_NO_HERCULES 0x02
|
||||
#define GRUB_VGA_CR_MODE_NO_CGA 0x01
|
||||
|
||||
enum
|
||||
{
|
||||
GRUB_VGA_SR_MAP_MASK_REGISTER = 0x02,
|
||||
GRUB_VGA_SR_MEMORY_MODE = 0x04,
|
||||
};
|
||||
|
||||
#define GRUB_VGA_SR_MEMORY_MODE_CHAIN4 8
|
||||
#define GRUB_VGA_SR_MEMORY_MODE_NORMAL 0
|
||||
|
||||
enum
|
||||
{
|
||||
GRUB_VGA_GR_READ_MAP_REGISTER = 0x04,
|
||||
GRUB_VGA_GR_MODE = 5,
|
||||
GRUB_VGA_GR_GR6 = 6,
|
||||
GRUB_VGA_GR_MAX
|
||||
};
|
||||
|
||||
#define GRUB_VGA_GR_GR6_GRAPHICS_MODE 1
|
||||
|
||||
#define GRUB_VGA_GR_MODE_256_COLOR 0x40
|
||||
#define GRUB_VGA_GR_MODE_READ_MODE1 0x08
|
||||
|
||||
static inline void
|
||||
grub_vga_gr_write (grub_uint8_t val, grub_uint8_t addr)
|
||||
{
|
||||
grub_outb (addr, GRUB_VGA_IO_GR_INDEX);
|
||||
grub_outb (val, GRUB_VGA_IO_GR_DATA);
|
||||
}
|
||||
|
||||
static inline grub_uint8_t
|
||||
grub_vga_gr_read (grub_uint8_t addr)
|
||||
{
|
||||
grub_outb (addr, GRUB_VGA_IO_GR_INDEX);
|
||||
return grub_inb (GRUB_VGA_IO_GR_DATA);
|
||||
}
|
||||
|
||||
static inline void
|
||||
grub_vga_cr_write (grub_uint8_t val, grub_uint8_t addr)
|
||||
{
|
||||
grub_outb (addr, GRUB_VGA_IO_CR_INDEX);
|
||||
grub_outb (val, GRUB_VGA_IO_CR_DATA);
|
||||
}
|
||||
|
||||
static inline grub_uint8_t
|
||||
grub_vga_cr_read (grub_uint8_t addr)
|
||||
{
|
||||
grub_outb (addr, GRUB_VGA_IO_CR_INDEX);
|
||||
return grub_inb (GRUB_VGA_IO_CR_DATA);
|
||||
}
|
||||
|
||||
static inline void
|
||||
grub_vga_sr_write (grub_uint8_t val, grub_uint8_t addr)
|
||||
{
|
||||
grub_outb (addr, GRUB_VGA_IO_SR_INDEX);
|
||||
grub_outb (val, GRUB_VGA_IO_SR_DATA);
|
||||
}
|
||||
|
||||
static inline grub_uint8_t
|
||||
grub_vga_sr_read (grub_uint8_t addr)
|
||||
{
|
||||
grub_outb (addr, GRUB_VGA_IO_SR_INDEX);
|
||||
return grub_inb (GRUB_VGA_IO_SR_DATA);
|
||||
}
|
||||
|
||||
static inline void
|
||||
grub_vga_palette_read (grub_uint8_t addr, grub_uint8_t *r, grub_uint8_t *g,
|
||||
grub_uint8_t *b)
|
||||
{
|
||||
grub_outb (addr, GRUB_VGA_IO_PALLETTE_READ_INDEX);
|
||||
*r = grub_inb (GRUB_VGA_IO_PALLETTE_DATA);
|
||||
*g = grub_inb (GRUB_VGA_IO_PALLETTE_DATA);
|
||||
*b = grub_inb (GRUB_VGA_IO_PALLETTE_DATA);
|
||||
}
|
||||
|
||||
static inline void
|
||||
grub_vga_palette_write (grub_uint8_t addr, grub_uint8_t r, grub_uint8_t g,
|
||||
grub_uint8_t b)
|
||||
{
|
||||
grub_outb (addr, GRUB_VGA_IO_PALLETTE_READ_INDEX);
|
||||
grub_outb (r, GRUB_VGA_IO_PALLETTE_DATA);
|
||||
grub_outb (g, GRUB_VGA_IO_PALLETTE_DATA);
|
||||
grub_outb (b, GRUB_VGA_IO_PALLETTE_DATA);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -184,6 +184,8 @@ typedef enum grub_video_driver_id
|
|||
GRUB_VIDEO_DRIVER_EFI_GOP,
|
||||
GRUB_VIDEO_DRIVER_SM712,
|
||||
GRUB_VIDEO_DRIVER_VGA,
|
||||
GRUB_VIDEO_DRIVER_CIRRUS,
|
||||
GRUB_VIDEO_DRIVER_BOCHS,
|
||||
GRUB_VIDEO_DRIVER_SDL
|
||||
} grub_video_driver_id_t;
|
||||
|
||||
|
|
|
@ -89,8 +89,8 @@ grub_video_fb_blit_bitmap (struct grub_video_bitmap *bitmap,
|
|||
|
||||
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,
|
||||
enum grub_video_blit_operators oper,
|
||||
int x, int y, int offset_x, int offset_y,
|
||||
unsigned int width, unsigned int height);
|
||||
|
||||
grub_err_t
|
||||
|
@ -119,11 +119,18 @@ typedef grub_err_t
|
|||
(*grub_video_fb_doublebuf_update_screen_t) (struct grub_video_fbrender_target *front,
|
||||
struct grub_video_fbrender_target *back);
|
||||
|
||||
typedef grub_err_t (*grub_video_fb_set_page_t) (int page);
|
||||
|
||||
grub_err_t
|
||||
grub_video_fb_doublebuf_blit_init (struct grub_video_fbrender_target **front,
|
||||
struct grub_video_fbrender_target **back,
|
||||
grub_video_fb_doublebuf_update_screen_t *update_screen,
|
||||
struct grub_video_mode_info mode_info,
|
||||
void *framebuf);
|
||||
grub_video_fb_setup (unsigned int mode_type, unsigned int mode_mask,
|
||||
struct grub_video_mode_info *mode_info,
|
||||
volatile void *page0_ptr,
|
||||
grub_video_fb_set_page_t set_page_in,
|
||||
volatile void *page1_ptr);
|
||||
grub_err_t
|
||||
grub_video_fb_swap_buffers (void);
|
||||
grub_err_t
|
||||
grub_video_fb_get_info_and_fini (struct grub_video_mode_info *mode_info,
|
||||
void **framebuf);
|
||||
|
||||
#endif /* ! GRUB_VIDEO_FB_HEADER */
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include <grub/i386/vga_common.h>
|
||||
#include <grub/i386/io.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/vga.h>
|
||||
|
||||
#define COLS 80
|
||||
#define ROWS 25
|
||||
|
@ -28,15 +29,6 @@ static int grub_curr_x, grub_curr_y;
|
|||
|
||||
#define VGA_TEXT_SCREEN 0xb8000
|
||||
|
||||
#define CRTC_ADDR_PORT 0x3D4
|
||||
#define CRTC_DATA_PORT 0x3D5
|
||||
|
||||
#define CRTC_CURSOR 0x0a
|
||||
#define CRTC_CURSOR_ADDR_HIGH 0x0e
|
||||
#define CRTC_CURSOR_ADDR_LOW 0x0f
|
||||
|
||||
#define CRTC_CURSOR_DISABLE (1 << 5)
|
||||
|
||||
static void
|
||||
screen_write_char (int x, int y, short c)
|
||||
{
|
||||
|
@ -53,10 +45,8 @@ static void
|
|||
update_cursor (void)
|
||||
{
|
||||
unsigned int pos = grub_curr_y * COLS + grub_curr_x;
|
||||
grub_outb (CRTC_CURSOR_ADDR_HIGH, CRTC_ADDR_PORT);
|
||||
grub_outb (pos >> 8, CRTC_DATA_PORT);
|
||||
grub_outb (CRTC_CURSOR_ADDR_LOW, CRTC_ADDR_PORT);
|
||||
grub_outb (pos & 0xFF, CRTC_DATA_PORT);
|
||||
grub_vga_cr_write (pos >> 8, GRUB_VGA_CR_CURSOR_ADDR_HIGH);
|
||||
grub_vga_cr_write (pos & 0xFF, GRUB_VGA_CR_CURSOR_ADDR_LOW);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -134,12 +124,11 @@ static void
|
|||
grub_vga_text_setcursor (int on)
|
||||
{
|
||||
grub_uint8_t old;
|
||||
grub_outb (CRTC_CURSOR, CRTC_ADDR_PORT);
|
||||
old = grub_inb (CRTC_DATA_PORT);
|
||||
old = grub_vga_cr_read (GRUB_VGA_CR_CURSOR);
|
||||
if (on)
|
||||
grub_outb (old & ~CRTC_CURSOR_DISABLE, CRTC_DATA_PORT);
|
||||
grub_vga_cr_write (old & ~GRUB_VGA_CR_CURSOR_DISABLE, GRUB_VGA_CR_CURSOR);
|
||||
else
|
||||
grub_outb (old | CRTC_CURSOR_DISABLE, CRTC_DATA_PORT);
|
||||
grub_vga_cr_write (old | GRUB_VGA_CR_CURSOR_DISABLE, GRUB_VGA_CR_CURSOR);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
|
|
423
video/bochs.c
Normal file
423
video/bochs.c
Normal file
|
@ -0,0 +1,423 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2006,2007,2008,2009,2010 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/>.
|
||||
*/
|
||||
|
||||
#define grub_video_render_target grub_video_fbrender_target
|
||||
|
||||
#include <grub/err.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/video.h>
|
||||
#include <grub/video_fb.h>
|
||||
#include <grub/pci.h>
|
||||
#include <grub/vga.h>
|
||||
|
||||
static struct
|
||||
{
|
||||
struct grub_video_mode_info mode_info;
|
||||
|
||||
grub_uint8_t *ptr;
|
||||
int mapped;
|
||||
grub_uint32_t base;
|
||||
grub_pci_device_t dev;
|
||||
} framebuffer;
|
||||
|
||||
#define BOCHS_APERTURE_SIZE 0x800000
|
||||
#define BOCHS_MAX_WIDTH 1600
|
||||
#define BOCHS_MAX_HEIGHT 1200
|
||||
#define BOCHS_WIDTH_ALIGN 8
|
||||
|
||||
enum
|
||||
{
|
||||
BOCHS_VBE_INDEX = 0x1ce,
|
||||
BOCHS_VBE_DATA = 0x1cf,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
BOCHS_VBE_WIDTH = 1,
|
||||
BOCHS_VBE_HEIGHT = 2,
|
||||
BOCHS_VBE_BPP = 3,
|
||||
BOCHS_VBE_ENABLE = 4,
|
||||
BOCHS_VBE_Y_OFFSET = 9,
|
||||
BOCHS_VBE_MAX
|
||||
};
|
||||
|
||||
static void
|
||||
vbe_write (grub_uint16_t val, grub_uint16_t addr)
|
||||
{
|
||||
grub_outw (addr, BOCHS_VBE_INDEX);
|
||||
grub_outw (val, BOCHS_VBE_DATA);
|
||||
}
|
||||
|
||||
static grub_uint16_t
|
||||
vbe_read (grub_uint16_t addr)
|
||||
{
|
||||
grub_outw (addr, BOCHS_VBE_INDEX);
|
||||
return grub_inw (BOCHS_VBE_DATA);
|
||||
}
|
||||
|
||||
struct saved_state
|
||||
{
|
||||
grub_uint8_t cr[256];
|
||||
grub_uint8_t gr[256];
|
||||
grub_uint8_t sr[256];
|
||||
grub_uint8_t r[256];
|
||||
grub_uint8_t g[256];
|
||||
grub_uint8_t b[256];
|
||||
grub_uint8_t vbe[BOCHS_VBE_MAX];
|
||||
int vbe_enable;
|
||||
/* We need to preserve VGA font and VGA text. */
|
||||
grub_uint8_t vram[32 * 4 * 256];
|
||||
};
|
||||
|
||||
static struct saved_state initial_state;
|
||||
static int state_saved = 0;
|
||||
|
||||
static void
|
||||
save_state (struct saved_state *st)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE (st->cr); i++)
|
||||
st->cr[i] = grub_vga_cr_read (i);
|
||||
for (i = 0; i < ARRAY_SIZE (st->gr); i++)
|
||||
st->gr[i] = grub_vga_gr_read (i);
|
||||
for (i = 0; i < ARRAY_SIZE (st->sr); i++)
|
||||
st->sr[i] = grub_vga_sr_read (i);
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
grub_vga_palette_read (i, st->r + i, st->g + i, st->b + i);
|
||||
|
||||
st->vbe_enable = vbe_read (BOCHS_VBE_ENABLE) & 1;
|
||||
if (st->vbe_enable)
|
||||
for (i = 0; i < ARRAY_SIZE (st->vbe); i++)
|
||||
st->vbe[i] = vbe_read (i);
|
||||
|
||||
grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_CHAIN4, GRUB_VGA_SR_MEMORY_MODE);
|
||||
grub_memcpy (st->vram, framebuffer.ptr, sizeof (st->vram));
|
||||
grub_vga_sr_write (st->sr[GRUB_VGA_SR_MEMORY_MODE], GRUB_VGA_SR_MEMORY_MODE);
|
||||
}
|
||||
|
||||
static void
|
||||
restore_state (struct saved_state *st)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
if (st->vbe_enable)
|
||||
for (i = 0; i < ARRAY_SIZE (st->vbe); i++)
|
||||
vbe_write (st->vbe[i], i);
|
||||
else
|
||||
vbe_write (0, BOCHS_VBE_ENABLE);
|
||||
|
||||
grub_vga_cr_write (0, 0x11);
|
||||
for (i = 0; i < ARRAY_SIZE (st->cr); i++)
|
||||
grub_vga_cr_write (st->cr[i], i);
|
||||
for (i = 0; i < ARRAY_SIZE (st->sr); i++)
|
||||
grub_vga_sr_write (st->sr[i], i);
|
||||
for (i = 0; i < ARRAY_SIZE (st->gr); i++)
|
||||
grub_vga_gr_write (st->gr[i], i);
|
||||
|
||||
for (i = 0; i < 256; i++)
|
||||
grub_vga_palette_write (i, st->r[i], st->g[i], st->b[i]);
|
||||
|
||||
grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_CHAIN4, GRUB_VGA_SR_MEMORY_MODE);
|
||||
grub_memcpy (framebuffer.ptr, st->vram, sizeof (st->vram));
|
||||
grub_vga_sr_write (st->sr[GRUB_VGA_SR_MEMORY_MODE], GRUB_VGA_SR_MEMORY_MODE);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_video_bochs_video_init (void)
|
||||
{
|
||||
/* Reset frame buffer. */
|
||||
grub_memset (&framebuffer, 0, sizeof(framebuffer));
|
||||
|
||||
return grub_video_fb_init ();
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_video_bochs_video_fini (void)
|
||||
{
|
||||
if (framebuffer.mapped)
|
||||
grub_pci_device_unmap_range (framebuffer.dev, framebuffer.ptr,
|
||||
BOCHS_APERTURE_SIZE);
|
||||
|
||||
if (state_saved)
|
||||
{
|
||||
restore_state (&initial_state);
|
||||
state_saved = 0;
|
||||
}
|
||||
|
||||
return grub_video_fb_fini ();
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
doublebuf_pageflipping_set_page (int page)
|
||||
{
|
||||
int start = framebuffer.mode_info.height * page;
|
||||
|
||||
vbe_write (start, BOCHS_VBE_Y_OFFSET);
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_video_bochs_set_palette (unsigned int start, unsigned int count,
|
||||
struct grub_video_palette_data *palette_data)
|
||||
{
|
||||
if (framebuffer.mode_info.mode_type == GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
|
||||
{
|
||||
unsigned i;
|
||||
if (start >= 0x100)
|
||||
return GRUB_ERR_NONE;
|
||||
if (start + count >= 0x100)
|
||||
count = 0x100 - start;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
grub_vga_palette_write (start + i, palette_data[i].r, palette_data[i].g,
|
||||
palette_data[i].b);
|
||||
}
|
||||
|
||||
/* Then set color to emulated palette. */
|
||||
return grub_video_fb_set_palette (start, count, palette_data);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_video_bochs_setup (unsigned int width, unsigned int height,
|
||||
unsigned int mode_type, unsigned int mode_mask)
|
||||
{
|
||||
int depth;
|
||||
grub_err_t err;
|
||||
int found = 0;
|
||||
int pitch, bytes_per_pixel;
|
||||
grub_size_t page_size; /* The size of a page in bytes. */
|
||||
|
||||
auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused)));
|
||||
int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid)
|
||||
{
|
||||
grub_pci_address_t addr;
|
||||
grub_uint32_t class;
|
||||
|
||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
|
||||
class = grub_pci_read (addr);
|
||||
|
||||
if (((class >> 16) & 0xffff) != 0x0300 || pciid != 0x11111234)
|
||||
return 0;
|
||||
|
||||
found = 1;
|
||||
|
||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
|
||||
framebuffer.base = grub_pci_read (addr) & GRUB_PCI_ADDR_MEM_MASK;
|
||||
framebuffer.dev = dev;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Decode depth from mode_type. If it is zero, then autodetect. */
|
||||
depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
|
||||
>> GRUB_VIDEO_MODE_TYPE_DEPTH_POS;
|
||||
|
||||
if (width == 0 || height == 0)
|
||||
{
|
||||
width = 800;
|
||||
height = 600;
|
||||
}
|
||||
|
||||
if (width > BOCHS_MAX_WIDTH)
|
||||
return grub_error (GRUB_ERR_IO, "width must be at most",
|
||||
BOCHS_MAX_WIDTH);
|
||||
|
||||
if (height > BOCHS_MAX_HEIGHT)
|
||||
return grub_error (GRUB_ERR_IO, "height must be at most",
|
||||
BOCHS_MAX_HEIGHT);
|
||||
|
||||
if (width & (BOCHS_WIDTH_ALIGN - 1))
|
||||
return grub_error (GRUB_ERR_IO, "width must be a multiple of %d",
|
||||
BOCHS_WIDTH_ALIGN);
|
||||
|
||||
if (depth == 0
|
||||
&& !grub_video_check_mode_flag (mode_type, mode_mask,
|
||||
GRUB_VIDEO_MODE_TYPE_INDEX_COLOR, 0))
|
||||
depth = 24;
|
||||
|
||||
if (depth == 0)
|
||||
depth = 8;
|
||||
|
||||
if (depth != 32 && depth != 24 && depth != 16 && depth != 15 && depth != 8
|
||||
&& depth != 4)
|
||||
return grub_error (GRUB_ERR_IO, "only 32, 24, 16, 15 and 8-bpp are"
|
||||
" supported by bochs video");
|
||||
|
||||
if (depth == 4)
|
||||
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "4-bpp isn't cupported");
|
||||
|
||||
bytes_per_pixel = (depth + 7) / 8;
|
||||
if (depth == 4)
|
||||
pitch = width / 2;
|
||||
else
|
||||
pitch = width * bytes_per_pixel;
|
||||
|
||||
page_size = pitch * height;
|
||||
|
||||
if (page_size > BOCHS_APERTURE_SIZE)
|
||||
return grub_error (GRUB_ERR_IO, "Not enough video memory for this mode");
|
||||
|
||||
grub_pci_iterate (find_card);
|
||||
if (!found)
|
||||
return grub_error (GRUB_ERR_IO, "Couldn't find graphics card");
|
||||
|
||||
if (found && framebuffer.base == 0)
|
||||
{
|
||||
/* FIXME: change framebuffer base */
|
||||
return grub_error (GRUB_ERR_IO, "PCI BAR not set");
|
||||
}
|
||||
|
||||
/* We can safely discard volatile attribute. */
|
||||
framebuffer.ptr = (void *) grub_pci_device_map_range (framebuffer.dev,
|
||||
framebuffer.base,
|
||||
BOCHS_APERTURE_SIZE);
|
||||
framebuffer.mapped = 1;
|
||||
|
||||
if (!state_saved)
|
||||
{
|
||||
save_state (&initial_state);
|
||||
state_saved = 1;
|
||||
}
|
||||
|
||||
{
|
||||
vbe_write (0, BOCHS_VBE_ENABLE);
|
||||
|
||||
vbe_write (width, BOCHS_VBE_WIDTH);
|
||||
vbe_write (height, BOCHS_VBE_HEIGHT);
|
||||
vbe_write (depth, BOCHS_VBE_BPP);
|
||||
|
||||
vbe_write (1, BOCHS_VBE_ENABLE);
|
||||
doublebuf_pageflipping_set_page (0);
|
||||
}
|
||||
|
||||
/* Fill mode info details. */
|
||||
framebuffer.mode_info.width = width;
|
||||
framebuffer.mode_info.height = height;
|
||||
framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB;
|
||||
framebuffer.mode_info.bpp = depth;
|
||||
framebuffer.mode_info.bytes_per_pixel = bytes_per_pixel;
|
||||
framebuffer.mode_info.pitch = pitch;
|
||||
framebuffer.mode_info.number_of_colors = 256;
|
||||
framebuffer.mode_info.reserved_mask_size = 0;
|
||||
framebuffer.mode_info.reserved_field_pos = 0;
|
||||
|
||||
switch (depth)
|
||||
{
|
||||
case 4:
|
||||
case 8:
|
||||
framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
|
||||
break;
|
||||
case 16:
|
||||
framebuffer.mode_info.red_mask_size = 5;
|
||||
framebuffer.mode_info.red_field_pos = 11;
|
||||
framebuffer.mode_info.green_mask_size = 6;
|
||||
framebuffer.mode_info.green_field_pos = 5;
|
||||
framebuffer.mode_info.blue_mask_size = 5;
|
||||
framebuffer.mode_info.blue_field_pos = 0;
|
||||
break;
|
||||
|
||||
case 15:
|
||||
framebuffer.mode_info.red_mask_size = 5;
|
||||
framebuffer.mode_info.red_field_pos = 10;
|
||||
framebuffer.mode_info.green_mask_size = 5;
|
||||
framebuffer.mode_info.green_field_pos = 5;
|
||||
framebuffer.mode_info.blue_mask_size = 5;
|
||||
framebuffer.mode_info.blue_field_pos = 0;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
framebuffer.mode_info.reserved_mask_size = 8;
|
||||
framebuffer.mode_info.reserved_field_pos = 24;
|
||||
|
||||
case 24:
|
||||
framebuffer.mode_info.red_mask_size = 8;
|
||||
framebuffer.mode_info.red_field_pos = 16;
|
||||
framebuffer.mode_info.green_mask_size = 8;
|
||||
framebuffer.mode_info.green_field_pos = 8;
|
||||
framebuffer.mode_info.blue_mask_size = 8;
|
||||
framebuffer.mode_info.blue_field_pos = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info);
|
||||
|
||||
if (BOCHS_APERTURE_SIZE >= 2 * page_size)
|
||||
err = grub_video_fb_setup (mode_type, mode_mask,
|
||||
&framebuffer.mode_info,
|
||||
framebuffer.ptr,
|
||||
doublebuf_pageflipping_set_page,
|
||||
framebuffer.ptr + page_size);
|
||||
else
|
||||
err = grub_video_fb_setup (mode_type, mode_mask,
|
||||
&framebuffer.mode_info,
|
||||
framebuffer.ptr, 0, 0);
|
||||
|
||||
|
||||
/* Copy default palette to initialize emulated palette. */
|
||||
err = grub_video_bochs_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
|
||||
grub_video_fbstd_colors);
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct grub_video_adapter grub_video_bochs_adapter =
|
||||
{
|
||||
.name = "Bochs PCI Video Driver",
|
||||
.id = GRUB_VIDEO_DRIVER_BOCHS,
|
||||
|
||||
.prio = GRUB_VIDEO_ADAPTER_PRIO_NATIVE,
|
||||
|
||||
.init = grub_video_bochs_video_init,
|
||||
.fini = grub_video_bochs_video_fini,
|
||||
.setup = grub_video_bochs_setup,
|
||||
.get_info = grub_video_fb_get_info,
|
||||
.get_info_and_fini = grub_video_fb_get_info_and_fini,
|
||||
.set_palette = grub_video_bochs_set_palette,
|
||||
.get_palette = grub_video_fb_get_palette,
|
||||
.set_viewport = grub_video_fb_set_viewport,
|
||||
.get_viewport = grub_video_fb_get_viewport,
|
||||
.map_color = grub_video_fb_map_color,
|
||||
.map_rgb = grub_video_fb_map_rgb,
|
||||
.map_rgba = grub_video_fb_map_rgba,
|
||||
.unmap_color = grub_video_fb_unmap_color,
|
||||
.fill_rect = grub_video_fb_fill_rect,
|
||||
.blit_bitmap = grub_video_fb_blit_bitmap,
|
||||
.blit_render_target = grub_video_fb_blit_render_target,
|
||||
.scroll = grub_video_fb_scroll,
|
||||
.swap_buffers = grub_video_fb_swap_buffers,
|
||||
.create_render_target = grub_video_fb_create_render_target,
|
||||
.delete_render_target = grub_video_fb_delete_render_target,
|
||||
.set_active_render_target = grub_video_fb_set_active_render_target,
|
||||
.get_active_render_target = grub_video_fb_get_active_render_target,
|
||||
|
||||
.next = 0
|
||||
};
|
||||
|
||||
GRUB_MOD_INIT(video_bochs)
|
||||
{
|
||||
grub_video_register (&grub_video_bochs_adapter);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(video_bochs)
|
||||
{
|
||||
grub_video_unregister (&grub_video_bochs_adapter);
|
||||
}
|
520
video/cirrus.c
Normal file
520
video/cirrus.c
Normal file
|
@ -0,0 +1,520 @@
|
|||
/*
|
||||
* GRUB -- GRand Unified Bootloader
|
||||
* Copyright (C) 2005,2006,2007,2008,2009,2010 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/>.
|
||||
*/
|
||||
|
||||
#define grub_video_render_target grub_video_fbrender_target
|
||||
|
||||
#include <grub/err.h>
|
||||
#include <grub/types.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/mm.h>
|
||||
#include <grub/video.h>
|
||||
#include <grub/video_fb.h>
|
||||
#include <grub/pci.h>
|
||||
#include <grub/vga.h>
|
||||
|
||||
static struct
|
||||
{
|
||||
struct grub_video_mode_info mode_info;
|
||||
grub_size_t page_size; /* The size of a page in bytes. */
|
||||
|
||||
grub_uint8_t *ptr;
|
||||
int mapped;
|
||||
grub_uint32_t base;
|
||||
grub_pci_device_t dev;
|
||||
} framebuffer;
|
||||
|
||||
#define CIRRUS_APERTURE_SIZE 0x1000000
|
||||
|
||||
#define CIRRUS_MAX_WIDTH 0x800
|
||||
#define CIRRUS_MAX_HEIGHT 0x800
|
||||
#define CIRRUS_MAX_PITCH (0x1ff * GRUB_VGA_CR_PITCH_DIVISOR)
|
||||
|
||||
enum
|
||||
{
|
||||
CIRRUS_CR_EXTENDED_DISPLAY = 0x1b,
|
||||
CIRRUS_CR_EXTENDED_OVERLAY = 0x1d,
|
||||
CIRRUS_CR_MAX
|
||||
};
|
||||
|
||||
#define CIRRUS_CR_EXTENDED_DISPLAY_PITCH_MASK 0x10
|
||||
#define CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT 4
|
||||
#define CIRRUS_CR_EXTENDED_DISPLAY_START_MASK1 0x1
|
||||
#define CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT1 16
|
||||
#define CIRRUS_CR_EXTENDED_DISPLAY_START_MASK2 0xc
|
||||
#define CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT2 15
|
||||
|
||||
#define CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_MASK 0x80
|
||||
#define CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_SHIFT 12
|
||||
|
||||
enum
|
||||
{
|
||||
CIRRUS_SR_EXTENDED_MODE = 7,
|
||||
CIRRUS_SR_MAX
|
||||
};
|
||||
|
||||
#define CIRRUS_SR_EXTENDED_MODE_LFB_ENABLE 0xf0
|
||||
#define CIRRUS_SR_EXTENDED_MODE_ENABLE_EXT 0x01
|
||||
#define CIRRUS_SR_EXTENDED_MODE_8BPP 0x00
|
||||
#define CIRRUS_SR_EXTENDED_MODE_16BPP 0x06
|
||||
#define CIRRUS_SR_EXTENDED_MODE_24BPP 0x04
|
||||
#define CIRRUS_SR_EXTENDED_MODE_32BPP 0x08
|
||||
|
||||
#define CIRRUS_HIDDEN_DAC_ENABLE_EXT 0x80
|
||||
#define CIRRUS_HIDDEN_DAC_ENABLE_ALL 0x40
|
||||
#define CIRRUS_HIDDEN_DAC_8BPP 0
|
||||
#define CIRRUS_HIDDEN_DAC_15BPP (CIRRUS_HIDDEN_DAC_ENABLE_EXT \
|
||||
| CIRRUS_HIDDEN_DAC_ENABLE_ALL | 0)
|
||||
#define CIRRUS_HIDDEN_DAC_16BPP (CIRRUS_HIDDEN_DAC_ENABLE_EXT \
|
||||
| CIRRUS_HIDDEN_DAC_ENABLE_ALL | 1)
|
||||
#define CIRRUS_HIDDEN_DAC_888COLOR (CIRRUS_HIDDEN_DAC_ENABLE_EXT \
|
||||
| CIRRUS_HIDDEN_DAC_ENABLE_ALL | 5)
|
||||
|
||||
static void
|
||||
write_hidden_dac (grub_uint8_t data)
|
||||
{
|
||||
grub_inb (GRUB_VGA_IO_PALLETTE_WRITE_INDEX);
|
||||
grub_inb (GRUB_VGA_IO_PIXEL_MASK);
|
||||
grub_inb (GRUB_VGA_IO_PIXEL_MASK);
|
||||
grub_inb (GRUB_VGA_IO_PIXEL_MASK);
|
||||
grub_inb (GRUB_VGA_IO_PIXEL_MASK);
|
||||
grub_outb (data, GRUB_VGA_IO_PIXEL_MASK);
|
||||
}
|
||||
|
||||
static grub_uint8_t
|
||||
read_hidden_dac (void)
|
||||
{
|
||||
grub_inb (GRUB_VGA_IO_PALLETTE_WRITE_INDEX);
|
||||
grub_inb (GRUB_VGA_IO_PIXEL_MASK);
|
||||
grub_inb (GRUB_VGA_IO_PIXEL_MASK);
|
||||
grub_inb (GRUB_VGA_IO_PIXEL_MASK);
|
||||
grub_inb (GRUB_VGA_IO_PIXEL_MASK);
|
||||
return grub_inb (GRUB_VGA_IO_PIXEL_MASK);
|
||||
}
|
||||
|
||||
struct saved_state
|
||||
{
|
||||
grub_uint8_t cr[CIRRUS_CR_MAX];
|
||||
grub_uint8_t gr[GRUB_VGA_GR_MAX];
|
||||
grub_uint8_t sr[CIRRUS_SR_MAX];
|
||||
grub_uint8_t hidden_dac;
|
||||
/* We need to preserve VGA font and VGA text. */
|
||||
grub_uint8_t vram[32 * 4 * 256];
|
||||
grub_uint8_t r[256];
|
||||
grub_uint8_t g[256];
|
||||
grub_uint8_t b[256];
|
||||
};
|
||||
|
||||
static struct saved_state initial_state;
|
||||
static int state_saved = 0;
|
||||
|
||||
static void
|
||||
save_state (struct saved_state *st)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < ARRAY_SIZE (st->cr); i++)
|
||||
st->cr[i] = grub_vga_cr_read (i);
|
||||
for (i = 0; i < ARRAY_SIZE (st->sr); i++)
|
||||
st->sr[i] = grub_vga_sr_read (i);
|
||||
for (i = 0; i < ARRAY_SIZE (st->gr); i++)
|
||||
st->gr[i] = grub_vga_gr_read (i);
|
||||
for (i = 0; i < 256; i++)
|
||||
grub_vga_palette_read (i, st->r + i, st->g + i, st->b + i);
|
||||
|
||||
st->hidden_dac = read_hidden_dac ();
|
||||
grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_CHAIN4, GRUB_VGA_SR_MEMORY_MODE);
|
||||
grub_memcpy (st->vram, framebuffer.ptr, sizeof (st->vram));
|
||||
}
|
||||
|
||||
static void
|
||||
restore_state (struct saved_state *st)
|
||||
{
|
||||
unsigned i;
|
||||
grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_CHAIN4, GRUB_VGA_SR_MEMORY_MODE);
|
||||
grub_memcpy (framebuffer.ptr, st->vram, sizeof (st->vram));
|
||||
for (i = 0; i < ARRAY_SIZE (st->cr); i++)
|
||||
grub_vga_cr_write (st->cr[i], i);
|
||||
for (i = 0; i < ARRAY_SIZE (st->sr); i++)
|
||||
grub_vga_sr_write (st->sr[i], i);
|
||||
for (i = 0; i < ARRAY_SIZE (st->gr); i++)
|
||||
grub_vga_gr_write (st->gr[i], i);
|
||||
for (i = 0; i < 256; i++)
|
||||
grub_vga_palette_write (i, st->r[i], st->g[i], st->b[i]);
|
||||
|
||||
write_hidden_dac (st->hidden_dac);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_video_cirrus_video_init (void)
|
||||
{
|
||||
/* Reset frame buffer. */
|
||||
grub_memset (&framebuffer, 0, sizeof(framebuffer));
|
||||
|
||||
return grub_video_fb_init ();
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_video_cirrus_video_fini (void)
|
||||
{
|
||||
if (framebuffer.mapped)
|
||||
grub_pci_device_unmap_range (framebuffer.dev, framebuffer.ptr,
|
||||
CIRRUS_APERTURE_SIZE);
|
||||
|
||||
if (state_saved)
|
||||
{
|
||||
restore_state (&initial_state);
|
||||
state_saved = 0;
|
||||
}
|
||||
|
||||
return grub_video_fb_fini ();
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
doublebuf_pageflipping_set_page (int page)
|
||||
{
|
||||
int start = framebuffer.page_size * page / 4;
|
||||
grub_uint8_t cr_ext, cr_overlay;
|
||||
|
||||
grub_vga_cr_write (start & 0xff, GRUB_VGA_CR_START_ADDR_LOW_REGISTER);
|
||||
grub_vga_cr_write ((start & 0xff00) >> 8,
|
||||
GRUB_VGA_CR_START_ADDR_HIGH_REGISTER);
|
||||
|
||||
cr_ext = grub_vga_cr_read (CIRRUS_CR_EXTENDED_DISPLAY);
|
||||
cr_ext &= ~(CIRRUS_CR_EXTENDED_DISPLAY_START_MASK1
|
||||
| CIRRUS_CR_EXTENDED_DISPLAY_START_MASK2);
|
||||
cr_ext |= ((start >> CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT1)
|
||||
& CIRRUS_CR_EXTENDED_DISPLAY_START_MASK1);
|
||||
cr_ext |= ((start >> CIRRUS_CR_EXTENDED_DISPLAY_START_SHIFT2)
|
||||
& CIRRUS_CR_EXTENDED_DISPLAY_START_MASK2);
|
||||
grub_vga_cr_write (cr_ext, CIRRUS_CR_EXTENDED_DISPLAY);
|
||||
|
||||
cr_overlay = grub_vga_cr_read (CIRRUS_CR_EXTENDED_OVERLAY);
|
||||
cr_overlay &= ~(CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_MASK);
|
||||
cr_overlay |= ((start >> CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_SHIFT)
|
||||
& CIRRUS_CR_EXTENDED_OVERLAY_DISPLAY_START_MASK);
|
||||
grub_vga_cr_write (cr_overlay, CIRRUS_CR_EXTENDED_OVERLAY);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_video_cirrus_set_palette (unsigned int start, unsigned int count,
|
||||
struct grub_video_palette_data *palette_data)
|
||||
{
|
||||
if (framebuffer.mode_info.mode_type == GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)
|
||||
{
|
||||
unsigned i;
|
||||
if (start >= 0x100)
|
||||
return GRUB_ERR_NONE;
|
||||
if (start + count >= 0x100)
|
||||
count = 0x100 - start;
|
||||
|
||||
for (i = 0; i < count; i++)
|
||||
grub_vga_palette_write (start + i, palette_data[i].r, palette_data[i].g,
|
||||
palette_data[i].b);
|
||||
}
|
||||
|
||||
/* Then set color to emulated palette. */
|
||||
return grub_video_fb_set_palette (start, count, palette_data);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_video_cirrus_setup (unsigned int width, unsigned int height,
|
||||
unsigned int mode_type, unsigned int mode_mask)
|
||||
{
|
||||
int depth;
|
||||
grub_err_t err;
|
||||
int found = 0;
|
||||
int pitch, bytes_per_pixel;
|
||||
|
||||
auto int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid __attribute__ ((unused)));
|
||||
int NESTED_FUNC_ATTR find_card (grub_pci_device_t dev, grub_pci_id_t pciid)
|
||||
{
|
||||
grub_pci_address_t addr;
|
||||
grub_uint32_t class;
|
||||
|
||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
|
||||
class = grub_pci_read (addr);
|
||||
|
||||
if (((class >> 16) & 0xffff) != 0x0300 || pciid != 0x00b81013)
|
||||
return 0;
|
||||
|
||||
found = 1;
|
||||
|
||||
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
|
||||
framebuffer.base = grub_pci_read (addr) & GRUB_PCI_ADDR_MEM_MASK;
|
||||
framebuffer.dev = dev;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Decode depth from mode_type. If it is zero, then autodetect. */
|
||||
depth = (mode_type & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
|
||||
>> GRUB_VIDEO_MODE_TYPE_DEPTH_POS;
|
||||
|
||||
if (width == 0 || height == 0)
|
||||
{
|
||||
width = 800;
|
||||
height = 600;
|
||||
}
|
||||
|
||||
if (width & (GRUB_VGA_CR_WIDTH_DIVISOR - 1))
|
||||
return grub_error (GRUB_ERR_IO,
|
||||
"screen width must be a multiple of %d",
|
||||
GRUB_VGA_CR_WIDTH_DIVISOR);
|
||||
|
||||
if (width > CIRRUS_MAX_WIDTH)
|
||||
return grub_error (GRUB_ERR_IO,
|
||||
"screen width must be at most %d", CIRRUS_MAX_WIDTH);
|
||||
|
||||
if (height > CIRRUS_MAX_HEIGHT)
|
||||
return grub_error (GRUB_ERR_IO,
|
||||
"screen height must be at most %d", CIRRUS_MAX_HEIGHT);
|
||||
|
||||
if (depth == 0
|
||||
&& !grub_video_check_mode_flag (mode_type, mode_mask,
|
||||
GRUB_VIDEO_MODE_TYPE_INDEX_COLOR, 0))
|
||||
depth = 24;
|
||||
|
||||
if (depth == 0)
|
||||
depth = 8;
|
||||
|
||||
if (depth != 32 && depth != 24 && depth != 16 && depth != 15 && depth != 8)
|
||||
return grub_error (GRUB_ERR_IO, "only 32, 24, 16, 15 and 8-bit bpp are"
|
||||
" supported by cirrus video");
|
||||
|
||||
bytes_per_pixel = (depth + 7) / 8;
|
||||
pitch = width * bytes_per_pixel;
|
||||
|
||||
if (pitch > CIRRUS_MAX_PITCH)
|
||||
return grub_error (GRUB_ERR_IO,
|
||||
"screen width must be at most %d at bitdepth %d",
|
||||
CIRRUS_MAX_PITCH / bytes_per_pixel, depth);
|
||||
|
||||
framebuffer.page_size = pitch * height;
|
||||
|
||||
if (framebuffer.page_size > CIRRUS_APERTURE_SIZE)
|
||||
return grub_error (GRUB_ERR_IO, "Not enough video memory for this mode");
|
||||
|
||||
grub_pci_iterate (find_card);
|
||||
if (!found)
|
||||
return grub_error (GRUB_ERR_IO, "Couldn't find graphics card");
|
||||
|
||||
if (found && framebuffer.base == 0)
|
||||
{
|
||||
/* FIXME: change framebuffer base */
|
||||
return grub_error (GRUB_ERR_IO, "PCI BAR not set");
|
||||
}
|
||||
|
||||
/* We can safely discard volatile attribute. */
|
||||
framebuffer.ptr = (void *) grub_pci_device_map_range (framebuffer.dev,
|
||||
framebuffer.base,
|
||||
CIRRUS_APERTURE_SIZE);
|
||||
framebuffer.mapped = 1;
|
||||
|
||||
if (!state_saved)
|
||||
{
|
||||
save_state (&initial_state);
|
||||
state_saved = 1;
|
||||
}
|
||||
|
||||
{
|
||||
int pitch_reg, overflow_reg = 0, line_compare = 0x3ff;
|
||||
grub_uint8_t sr_ext = 0, hidden_dac = 0;
|
||||
|
||||
pitch_reg = pitch / GRUB_VGA_CR_PITCH_DIVISOR;
|
||||
|
||||
grub_vga_gr_write (GRUB_VGA_GR_MODE_256_COLOR | GRUB_VGA_GR_MODE_READ_MODE1,
|
||||
GRUB_VGA_GR_MODE);
|
||||
grub_vga_gr_write (GRUB_VGA_GR_GR6_GRAPHICS_MODE, GRUB_VGA_GR_GR6);
|
||||
|
||||
grub_vga_sr_write (GRUB_VGA_SR_MEMORY_MODE_NORMAL, GRUB_VGA_SR_MEMORY_MODE);
|
||||
|
||||
/* Disable CR0-7 write protection. */
|
||||
grub_vga_cr_write (0, GRUB_VGA_CR_VSYNC_END);
|
||||
|
||||
grub_vga_cr_write (width / GRUB_VGA_CR_WIDTH_DIVISOR - 1,
|
||||
GRUB_VGA_CR_WIDTH);
|
||||
grub_vga_cr_write ((height - 1) & 0xff, GRUB_VGA_CR_HEIGHT);
|
||||
overflow_reg |= (((height - 1) >> GRUB_VGA_CR_OVERFLOW_HEIGHT1_SHIFT) &
|
||||
GRUB_VGA_CR_OVERFLOW_HEIGHT1_MASK)
|
||||
| (((height - 1) >> GRUB_VGA_CR_OVERFLOW_HEIGHT2_SHIFT) &
|
||||
GRUB_VGA_CR_OVERFLOW_HEIGHT2_MASK);
|
||||
|
||||
grub_vga_cr_write (pitch_reg & 0xff, GRUB_VGA_CR_PITCH);
|
||||
|
||||
grub_vga_cr_write (line_compare & 0xff, GRUB_VGA_CR_LINE_COMPARE);
|
||||
overflow_reg |= (line_compare >> GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_SHIFT)
|
||||
& GRUB_VGA_CR_OVERFLOW_LINE_COMPARE_MASK;
|
||||
|
||||
grub_vga_cr_write (overflow_reg, GRUB_VGA_CR_OVERFLOW);
|
||||
|
||||
grub_vga_cr_write ((pitch_reg >> CIRRUS_CR_EXTENDED_DISPLAY_PITCH_SHIFT)
|
||||
& CIRRUS_CR_EXTENDED_DISPLAY_PITCH_MASK,
|
||||
CIRRUS_CR_EXTENDED_DISPLAY);
|
||||
|
||||
grub_vga_cr_write ((line_compare >> GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_SHIFT)
|
||||
& GRUB_VGA_CR_CELL_HEIGHT_LINE_COMPARE_MASK, GRUB_VGA_CR_CELL_HEIGHT);
|
||||
|
||||
grub_vga_cr_write (GRUB_VGA_CR_MODE_TIMING_ENABLE
|
||||
| GRUB_VGA_CR_MODE_BYTE_MODE
|
||||
| GRUB_VGA_CR_MODE_NO_HERCULES | GRUB_VGA_CR_MODE_NO_CGA,
|
||||
GRUB_VGA_CR_MODE);
|
||||
|
||||
doublebuf_pageflipping_set_page (0);
|
||||
|
||||
sr_ext = CIRRUS_SR_EXTENDED_MODE_LFB_ENABLE
|
||||
| CIRRUS_SR_EXTENDED_MODE_ENABLE_EXT;
|
||||
switch (depth)
|
||||
{
|
||||
/* FIXME: support 8-bit grayscale and 8-bit RGB. */
|
||||
case 32:
|
||||
hidden_dac = CIRRUS_HIDDEN_DAC_888COLOR;
|
||||
sr_ext |= CIRRUS_SR_EXTENDED_MODE_32BPP;
|
||||
break;
|
||||
case 24:
|
||||
hidden_dac = CIRRUS_HIDDEN_DAC_888COLOR;
|
||||
sr_ext |= CIRRUS_SR_EXTENDED_MODE_24BPP;
|
||||
break;
|
||||
case 16:
|
||||
hidden_dac = CIRRUS_HIDDEN_DAC_16BPP;
|
||||
sr_ext |= CIRRUS_SR_EXTENDED_MODE_16BPP;
|
||||
break;
|
||||
case 15:
|
||||
hidden_dac = CIRRUS_HIDDEN_DAC_15BPP;
|
||||
sr_ext |= CIRRUS_SR_EXTENDED_MODE_16BPP;
|
||||
break;
|
||||
case 8:
|
||||
hidden_dac = CIRRUS_HIDDEN_DAC_8BPP;
|
||||
sr_ext |= CIRRUS_SR_EXTENDED_MODE_8BPP;
|
||||
break;
|
||||
}
|
||||
grub_vga_sr_write (sr_ext, CIRRUS_SR_EXTENDED_MODE);
|
||||
write_hidden_dac (hidden_dac);
|
||||
}
|
||||
|
||||
/* Fill mode info details. */
|
||||
framebuffer.mode_info.width = width;
|
||||
framebuffer.mode_info.height = height;
|
||||
framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB;
|
||||
framebuffer.mode_info.bpp = depth;
|
||||
framebuffer.mode_info.bytes_per_pixel = bytes_per_pixel;
|
||||
framebuffer.mode_info.pitch = pitch;
|
||||
framebuffer.mode_info.number_of_colors = 256;
|
||||
framebuffer.mode_info.reserved_mask_size = 0;
|
||||
framebuffer.mode_info.reserved_field_pos = 0;
|
||||
|
||||
switch (depth)
|
||||
{
|
||||
case 8:
|
||||
framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
|
||||
break;
|
||||
case 16:
|
||||
framebuffer.mode_info.red_mask_size = 5;
|
||||
framebuffer.mode_info.red_field_pos = 11;
|
||||
framebuffer.mode_info.green_mask_size = 6;
|
||||
framebuffer.mode_info.green_field_pos = 5;
|
||||
framebuffer.mode_info.blue_mask_size = 5;
|
||||
framebuffer.mode_info.blue_field_pos = 0;
|
||||
break;
|
||||
|
||||
case 15:
|
||||
framebuffer.mode_info.red_mask_size = 5;
|
||||
framebuffer.mode_info.red_field_pos = 10;
|
||||
framebuffer.mode_info.green_mask_size = 5;
|
||||
framebuffer.mode_info.green_field_pos = 5;
|
||||
framebuffer.mode_info.blue_mask_size = 5;
|
||||
framebuffer.mode_info.blue_field_pos = 0;
|
||||
break;
|
||||
|
||||
case 32:
|
||||
framebuffer.mode_info.reserved_mask_size = 8;
|
||||
framebuffer.mode_info.reserved_field_pos = 24;
|
||||
|
||||
case 24:
|
||||
framebuffer.mode_info.red_mask_size = 8;
|
||||
framebuffer.mode_info.red_field_pos = 16;
|
||||
framebuffer.mode_info.green_mask_size = 8;
|
||||
framebuffer.mode_info.green_field_pos = 8;
|
||||
framebuffer.mode_info.blue_mask_size = 8;
|
||||
framebuffer.mode_info.blue_field_pos = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info);
|
||||
|
||||
if (CIRRUS_APERTURE_SIZE >= 2 * framebuffer.page_size)
|
||||
err = grub_video_fb_setup (mode_type, mode_mask,
|
||||
&framebuffer.mode_info,
|
||||
framebuffer.ptr,
|
||||
doublebuf_pageflipping_set_page,
|
||||
framebuffer.ptr + framebuffer.page_size);
|
||||
else
|
||||
err = grub_video_fb_setup (mode_type, mode_mask,
|
||||
&framebuffer.mode_info,
|
||||
framebuffer.ptr, 0, 0);
|
||||
|
||||
|
||||
/* Copy default palette to initialize emulated palette. */
|
||||
err = grub_video_cirrus_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
|
||||
grub_video_fbstd_colors);
|
||||
return err;
|
||||
}
|
||||
|
||||
static struct grub_video_adapter grub_video_cirrus_adapter =
|
||||
{
|
||||
.name = "Cirrus CLGD 5446 PCI Video Driver",
|
||||
.id = GRUB_VIDEO_DRIVER_CIRRUS,
|
||||
|
||||
.prio = GRUB_VIDEO_ADAPTER_PRIO_NATIVE,
|
||||
|
||||
.init = grub_video_cirrus_video_init,
|
||||
.fini = grub_video_cirrus_video_fini,
|
||||
.setup = grub_video_cirrus_setup,
|
||||
.get_info = grub_video_fb_get_info,
|
||||
.get_info_and_fini = grub_video_fb_get_info_and_fini,
|
||||
.set_palette = grub_video_cirrus_set_palette,
|
||||
.get_palette = grub_video_fb_get_palette,
|
||||
.set_viewport = grub_video_fb_set_viewport,
|
||||
.get_viewport = grub_video_fb_get_viewport,
|
||||
.map_color = grub_video_fb_map_color,
|
||||
.map_rgb = grub_video_fb_map_rgb,
|
||||
.map_rgba = grub_video_fb_map_rgba,
|
||||
.unmap_color = grub_video_fb_unmap_color,
|
||||
.fill_rect = grub_video_fb_fill_rect,
|
||||
.blit_bitmap = grub_video_fb_blit_bitmap,
|
||||
.blit_render_target = grub_video_fb_blit_render_target,
|
||||
.scroll = grub_video_fb_scroll,
|
||||
.swap_buffers = grub_video_fb_swap_buffers,
|
||||
.create_render_target = grub_video_fb_create_render_target,
|
||||
.delete_render_target = grub_video_fb_delete_render_target,
|
||||
.set_active_render_target = grub_video_fb_set_active_render_target,
|
||||
.get_active_render_target = grub_video_fb_get_active_render_target,
|
||||
|
||||
.next = 0
|
||||
};
|
||||
|
||||
GRUB_MOD_INIT(video_cirrus)
|
||||
{
|
||||
grub_video_register (&grub_video_cirrus_adapter);
|
||||
}
|
||||
|
||||
GRUB_MOD_FINI(video_cirrus)
|
||||
{
|
||||
grub_video_unregister (&grub_video_cirrus_adapter);
|
||||
}
|
|
@ -25,9 +25,20 @@
|
|||
#include <grub/fbutil.h>
|
||||
#include <grub/bitmap.h>
|
||||
|
||||
static struct grub_video_fbrender_target *render_target;
|
||||
struct grub_video_palette_data *palette;
|
||||
static unsigned int palette_size;
|
||||
static struct
|
||||
{
|
||||
struct grub_video_fbrender_target *render_target;
|
||||
struct grub_video_fbrender_target *front_target;
|
||||
struct grub_video_fbrender_target *back_target;
|
||||
struct grub_video_palette_data *palette;
|
||||
unsigned int palette_size;
|
||||
/* For page flipping strategy. */
|
||||
int displayed_page; /* The page # that is the front buffer. */
|
||||
int render_page; /* The page # that is the back buffer. */
|
||||
grub_video_fb_set_page_t set_page;
|
||||
char *offscreen_buffer;
|
||||
grub_video_fb_doublebuf_update_screen_t update_screen;
|
||||
} framebuffer;
|
||||
|
||||
/* Specify "standard" VGA palette, some video cards may
|
||||
need this and this will also be used when using RGB modes. */
|
||||
|
@ -56,10 +67,13 @@ struct grub_video_palette_data grub_video_fbstd_colors[GRUB_VIDEO_FBSTD_NUMCOLOR
|
|||
grub_err_t
|
||||
grub_video_fb_init (void)
|
||||
{
|
||||
grub_free (palette);
|
||||
render_target = 0;
|
||||
palette = 0;
|
||||
palette_size = 0;
|
||||
grub_free (framebuffer.palette);
|
||||
framebuffer.render_target = 0;
|
||||
framebuffer.front_target = 0;
|
||||
framebuffer.back_target = 0;
|
||||
framebuffer.palette = 0;
|
||||
framebuffer.palette_size = 0;
|
||||
framebuffer.set_page = 0;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
@ -68,10 +82,15 @@ grub_video_fb_fini (void)
|
|||
{
|
||||
/* TODO: destroy render targets. */
|
||||
|
||||
grub_free (palette);
|
||||
render_target = 0;
|
||||
palette = 0;
|
||||
palette_size = 0;
|
||||
grub_free (framebuffer.offscreen_buffer);
|
||||
grub_free (framebuffer.palette);
|
||||
framebuffer.render_target = 0;
|
||||
framebuffer.front_target = 0;
|
||||
framebuffer.back_target = 0;
|
||||
framebuffer.palette = 0;
|
||||
framebuffer.palette_size = 0;
|
||||
framebuffer.set_page = 0;
|
||||
framebuffer.offscreen_buffer = 0;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
@ -79,7 +98,7 @@ grub_err_t
|
|||
grub_video_fb_get_info (struct grub_video_mode_info *mode_info)
|
||||
{
|
||||
/* Copy mode info from active render target. */
|
||||
grub_memcpy (mode_info, &render_target->mode_info,
|
||||
grub_memcpy (mode_info, &framebuffer.render_target->mode_info,
|
||||
sizeof (struct grub_video_mode_info));
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
@ -92,8 +111,8 @@ grub_video_fb_get_palette (unsigned int start, unsigned int count,
|
|||
unsigned int i;
|
||||
|
||||
/* Assume that we know everything from index color palette. */
|
||||
for (i = 0; (i < count) && ((i + start) < palette_size); i++)
|
||||
palette_data[i] = palette[start + i];
|
||||
for (i = 0; (i < count) && ((i + start) < framebuffer.palette_size); i++)
|
||||
palette_data[i] = framebuffer.palette[start + i];
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
@ -103,18 +122,20 @@ grub_video_fb_set_palette (unsigned int start, unsigned int count,
|
|||
struct grub_video_palette_data *palette_data)
|
||||
{
|
||||
unsigned i;
|
||||
if (start + count > palette_size)
|
||||
if (start + count > framebuffer.palette_size)
|
||||
{
|
||||
palette_size = start + count;
|
||||
palette = grub_realloc (palette, sizeof (palette[0]) * palette_size);
|
||||
if (!palette)
|
||||
framebuffer.palette_size = start + count;
|
||||
framebuffer.palette = grub_realloc (framebuffer.palette,
|
||||
sizeof (framebuffer.palette[0])
|
||||
* framebuffer.palette_size);
|
||||
if (!framebuffer.palette)
|
||||
{
|
||||
grub_video_fb_fini ();
|
||||
return grub_errno;
|
||||
}
|
||||
}
|
||||
for (i = 0; (i < count) && ((i + start) < palette_size); i++)
|
||||
palette[start + i] = palette_data[i];
|
||||
for (i = 0; (i < count) && ((i + start) < framebuffer.palette_size); i++)
|
||||
framebuffer.palette[start + i] = palette_data[i];
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
@ -124,28 +145,28 @@ grub_video_fb_set_viewport (unsigned int x, unsigned int y,
|
|||
{
|
||||
/* 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)
|
||||
if (x > framebuffer.render_target->mode_info.width)
|
||||
{
|
||||
x = 0;
|
||||
width = 0;
|
||||
}
|
||||
|
||||
if (y > render_target->mode_info.height)
|
||||
if (y > framebuffer.render_target->mode_info.height)
|
||||
{
|
||||
y = 0;
|
||||
height = 0;
|
||||
}
|
||||
|
||||
if (x + width > render_target->mode_info.width)
|
||||
width = render_target->mode_info.width - x;
|
||||
if (x + width > framebuffer.render_target->mode_info.width)
|
||||
width = framebuffer.render_target->mode_info.width - x;
|
||||
|
||||
if (y + height > render_target->mode_info.height)
|
||||
height = render_target->mode_info.height - y;
|
||||
if (y + height > framebuffer.render_target->mode_info.height)
|
||||
height = framebuffer.render_target->mode_info.height - y;
|
||||
|
||||
render_target->viewport.x = x;
|
||||
render_target->viewport.y = y;
|
||||
render_target->viewport.width = width;
|
||||
render_target->viewport.height = height;
|
||||
framebuffer.render_target->viewport.x = x;
|
||||
framebuffer.render_target->viewport.y = y;
|
||||
framebuffer.render_target->viewport.width = width;
|
||||
framebuffer.render_target->viewport.height = height;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
@ -154,10 +175,10 @@ grub_err_t
|
|||
grub_video_fb_get_viewport (unsigned int *x, unsigned int *y,
|
||||
unsigned int *width, unsigned int *height)
|
||||
{
|
||||
if (x) *x = render_target->viewport.x;
|
||||
if (y) *y = render_target->viewport.y;
|
||||
if (width) *width = render_target->viewport.width;
|
||||
if (height) *height = render_target->viewport.height;
|
||||
if (x) *x = framebuffer.render_target->viewport.x;
|
||||
if (y) *y = framebuffer.render_target->viewport.y;
|
||||
if (width) *width = framebuffer.render_target->viewport.width;
|
||||
if (height) *height = framebuffer.render_target->viewport.height;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
@ -168,18 +189,18 @@ grub_video_fb_map_color (grub_uint32_t color_name)
|
|||
{
|
||||
/* TODO: implement color theme mapping code. */
|
||||
|
||||
if (color_name < palette_size)
|
||||
if (color_name < framebuffer.palette_size)
|
||||
{
|
||||
if ((render_target->mode_info.mode_type
|
||||
if ((framebuffer.render_target->mode_info.mode_type
|
||||
& GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
|
||||
return color_name;
|
||||
else
|
||||
{
|
||||
grub_video_color_t color;
|
||||
|
||||
color = grub_video_fb_map_rgb (palette[color_name].r,
|
||||
palette[color_name].g,
|
||||
palette[color_name].b);
|
||||
color = grub_video_fb_map_rgb (framebuffer.palette[color_name].r,
|
||||
framebuffer.palette[color_name].g,
|
||||
framebuffer.palette[color_name].b);
|
||||
|
||||
return color;
|
||||
}
|
||||
|
@ -193,7 +214,7 @@ grub_video_color_t
|
|||
grub_video_fb_map_rgb (grub_uint8_t red, grub_uint8_t green,
|
||||
grub_uint8_t blue)
|
||||
{
|
||||
if ((render_target->mode_info.mode_type
|
||||
if ((framebuffer.render_target->mode_info.mode_type
|
||||
& GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
|
||||
{
|
||||
int minindex = 0;
|
||||
|
@ -203,13 +224,13 @@ grub_video_fb_map_rgb (grub_uint8_t red, grub_uint8_t green,
|
|||
unsigned i;
|
||||
|
||||
/* Find best matching color. */
|
||||
for (i = 0; i < palette_size; i++)
|
||||
for (i = 0; i < framebuffer.palette_size; i++)
|
||||
{
|
||||
val = palette[i].r - red;
|
||||
val = framebuffer.palette[i].r - red;
|
||||
tmp = val * val;
|
||||
val = palette[i].g - green;
|
||||
val = framebuffer.palette[i].g - green;
|
||||
tmp += val * val;
|
||||
val = palette[i].b - blue;
|
||||
val = framebuffer.palette[i].b - blue;
|
||||
tmp += val * val;
|
||||
|
||||
if (i == 0)
|
||||
|
@ -226,12 +247,12 @@ grub_video_fb_map_rgb (grub_uint8_t red, grub_uint8_t green,
|
|||
|
||||
return minindex;
|
||||
}
|
||||
else if ((render_target->mode_info.mode_type
|
||||
else if ((framebuffer.render_target->mode_info.mode_type
|
||||
& GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0)
|
||||
{
|
||||
if (red == render_target->mode_info.fg_red
|
||||
&& green == render_target->mode_info.fg_green
|
||||
&& blue == render_target->mode_info.fg_blue)
|
||||
if (red == framebuffer.render_target->mode_info.fg_red
|
||||
&& green == framebuffer.render_target->mode_info.fg_green
|
||||
&& blue == framebuffer.render_target->mode_info.fg_blue)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
|
@ -241,15 +262,15 @@ grub_video_fb_map_rgb (grub_uint8_t red, grub_uint8_t green,
|
|||
grub_uint32_t value;
|
||||
grub_uint8_t alpha = 255; /* Opaque color. */
|
||||
|
||||
red >>= 8 - render_target->mode_info.red_mask_size;
|
||||
green >>= 8 - render_target->mode_info.green_mask_size;
|
||||
blue >>= 8 - render_target->mode_info.blue_mask_size;
|
||||
alpha >>= 8 - render_target->mode_info.reserved_mask_size;
|
||||
red >>= 8 - framebuffer.render_target->mode_info.red_mask_size;
|
||||
green >>= 8 - framebuffer.render_target->mode_info.green_mask_size;
|
||||
blue >>= 8 - framebuffer.render_target->mode_info.blue_mask_size;
|
||||
alpha >>= 8 - framebuffer.render_target->mode_info.reserved_mask_size;
|
||||
|
||||
value = red << render_target->mode_info.red_field_pos;
|
||||
value |= green << render_target->mode_info.green_field_pos;
|
||||
value |= blue << render_target->mode_info.blue_field_pos;
|
||||
value |= alpha << render_target->mode_info.reserved_field_pos;
|
||||
value = red << framebuffer.render_target->mode_info.red_field_pos;
|
||||
value |= green << framebuffer.render_target->mode_info.green_field_pos;
|
||||
value |= blue << framebuffer.render_target->mode_info.blue_field_pos;
|
||||
value |= alpha << framebuffer.render_target->mode_info.reserved_field_pos;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -261,18 +282,18 @@ grub_video_color_t
|
|||
grub_video_fb_map_rgba (grub_uint8_t red, grub_uint8_t green,
|
||||
grub_uint8_t blue, grub_uint8_t alpha)
|
||||
{
|
||||
if ((render_target->mode_info.mode_type
|
||||
if ((framebuffer.render_target->mode_info.mode_type
|
||||
& GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
|
||||
/* No alpha available in index color modes, just use
|
||||
same value as in only RGB modes. */
|
||||
return grub_video_fb_map_rgb (red, green, blue);
|
||||
else if ((render_target->mode_info.mode_type
|
||||
else if ((framebuffer.render_target->mode_info.mode_type
|
||||
& GRUB_VIDEO_MODE_TYPE_1BIT_BITMAP) != 0)
|
||||
{
|
||||
if (red == render_target->mode_info.fg_red
|
||||
&& green == render_target->mode_info.fg_green
|
||||
&& blue == render_target->mode_info.fg_blue
|
||||
&& alpha == render_target->mode_info.fg_alpha)
|
||||
if (red == framebuffer.render_target->mode_info.fg_red
|
||||
&& green == framebuffer.render_target->mode_info.fg_green
|
||||
&& blue == framebuffer.render_target->mode_info.fg_blue
|
||||
&& alpha == framebuffer.render_target->mode_info.fg_alpha)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
|
@ -281,15 +302,15 @@ grub_video_fb_map_rgba (grub_uint8_t red, grub_uint8_t green,
|
|||
{
|
||||
grub_uint32_t value;
|
||||
|
||||
red >>= 8 - render_target->mode_info.red_mask_size;
|
||||
green >>= 8 - render_target->mode_info.green_mask_size;
|
||||
blue >>= 8 - render_target->mode_info.blue_mask_size;
|
||||
alpha >>= 8 - render_target->mode_info.reserved_mask_size;
|
||||
red >>= 8 - framebuffer.render_target->mode_info.red_mask_size;
|
||||
green >>= 8 - framebuffer.render_target->mode_info.green_mask_size;
|
||||
blue >>= 8 - framebuffer.render_target->mode_info.blue_mask_size;
|
||||
alpha >>= 8 - framebuffer.render_target->mode_info.reserved_mask_size;
|
||||
|
||||
value = red << render_target->mode_info.red_field_pos;
|
||||
value |= green << render_target->mode_info.green_field_pos;
|
||||
value |= blue << render_target->mode_info.blue_field_pos;
|
||||
value |= alpha << render_target->mode_info.reserved_field_pos;
|
||||
value = red << framebuffer.render_target->mode_info.red_field_pos;
|
||||
value |= green << framebuffer.render_target->mode_info.green_field_pos;
|
||||
value |= blue << framebuffer.render_target->mode_info.blue_field_pos;
|
||||
value |= alpha << framebuffer.render_target->mode_info.reserved_field_pos;
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -303,8 +324,8 @@ grub_video_fb_unmap_color (grub_video_color_t color,
|
|||
{
|
||||
struct grub_video_fbblit_info target_info;
|
||||
|
||||
target_info.mode_info = &render_target->mode_info;
|
||||
target_info.data = render_target->data;
|
||||
target_info.mode_info = &framebuffer.render_target->mode_info;
|
||||
target_info.data = framebuffer.render_target->data;
|
||||
|
||||
grub_video_fb_unmap_color_int (&target_info, color, red, green, blue, alpha);
|
||||
|
||||
|
@ -334,10 +355,10 @@ grub_video_fb_unmap_color_int (struct grub_video_fbblit_info * source,
|
|||
return;
|
||||
}
|
||||
|
||||
*red = palette[color].r;
|
||||
*green = palette[color].g;
|
||||
*blue = palette[color].b;
|
||||
*alpha = palette[color].a;
|
||||
*red = framebuffer.palette[color].r;
|
||||
*green = framebuffer.palette[color].g;
|
||||
*blue = framebuffer.palette[color].b;
|
||||
*alpha = framebuffer.palette[color].a;
|
||||
return;
|
||||
}
|
||||
else if ((mode_info->mode_type
|
||||
|
@ -406,9 +427,9 @@ grub_video_fb_fill_rect (grub_video_color_t color, int x, int y,
|
|||
struct grub_video_fbblit_info target;
|
||||
|
||||
/* Make sure there is something to do. */
|
||||
if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0))
|
||||
if ((x >= (int)framebuffer.render_target->viewport.width) || (x + (int)width < 0))
|
||||
return GRUB_ERR_NONE;
|
||||
if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0))
|
||||
if ((y >= (int)framebuffer.render_target->viewport.height) || (y + (int)height < 0))
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
/* Do not allow drawing out of viewport. */
|
||||
|
@ -423,18 +444,18 @@ grub_video_fb_fill_rect (grub_video_color_t color, int x, int y,
|
|||
y = 0;
|
||||
}
|
||||
|
||||
if ((x + width) > render_target->viewport.width)
|
||||
width = render_target->viewport.width - x;
|
||||
if ((y + height) > render_target->viewport.height)
|
||||
height = render_target->viewport.height - y;
|
||||
if ((x + width) > framebuffer.render_target->viewport.width)
|
||||
width = framebuffer.render_target->viewport.width - x;
|
||||
if ((y + height) > framebuffer.render_target->viewport.height)
|
||||
height = framebuffer.render_target->viewport.height - y;
|
||||
|
||||
/* Add viewport offset. */
|
||||
x += render_target->viewport.x;
|
||||
y += render_target->viewport.y;
|
||||
x += framebuffer.render_target->viewport.x;
|
||||
y += framebuffer.render_target->viewport.y;
|
||||
|
||||
/* Use fbblit_info to encapsulate rendering. */
|
||||
target.mode_info = &render_target->mode_info;
|
||||
target.data = render_target->data;
|
||||
target.mode_info = &framebuffer.render_target->mode_info;
|
||||
target.data = framebuffer.render_target->data;
|
||||
|
||||
/* Try to figure out more optimized version. Note that color is already
|
||||
mapped to target format so we can make assumptions based on that. */
|
||||
|
@ -761,9 +782,9 @@ grub_video_fb_blit_bitmap (struct grub_video_bitmap *bitmap,
|
|||
/* 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 >= (int)framebuffer.render_target->viewport.width) || (x + (int)width < 0))
|
||||
return GRUB_ERR_NONE;
|
||||
if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0))
|
||||
if ((y >= (int)framebuffer.render_target->viewport.height) || (y + (int)height < 0))
|
||||
return GRUB_ERR_NONE;
|
||||
if ((x + (int)bitmap->mode_info.width) < 0)
|
||||
return GRUB_ERR_NONE;
|
||||
|
@ -806,10 +827,10 @@ grub_video_fb_blit_bitmap (struct grub_video_bitmap *bitmap,
|
|||
}
|
||||
|
||||
/* Do not allow drawing out of viewport. */
|
||||
if ((x + width) > render_target->viewport.width)
|
||||
width = render_target->viewport.width - x;
|
||||
if ((y + height) > render_target->viewport.height)
|
||||
height = render_target->viewport.height - y;
|
||||
if ((x + width) > framebuffer.render_target->viewport.width)
|
||||
width = framebuffer.render_target->viewport.width - x;
|
||||
if ((y + height) > framebuffer.render_target->viewport.height)
|
||||
height = framebuffer.render_target->viewport.height - y;
|
||||
|
||||
if ((offset_x + width) > bitmap->mode_info.width)
|
||||
width = bitmap->mode_info.width - offset_x;
|
||||
|
@ -824,14 +845,14 @@ grub_video_fb_blit_bitmap (struct grub_video_bitmap *bitmap,
|
|||
height = bitmap->mode_info.height;
|
||||
|
||||
/* Add viewport offset. */
|
||||
x += render_target->viewport.x;
|
||||
y += render_target->viewport.y;
|
||||
x += framebuffer.render_target->viewport.x;
|
||||
y += framebuffer.render_target->viewport.y;
|
||||
|
||||
/* Use fbblit_info to encapsulate rendering. */
|
||||
source.mode_info = &bitmap->mode_info;
|
||||
source.data = bitmap->data;
|
||||
target.mode_info = &render_target->mode_info;
|
||||
target.data = render_target->data;
|
||||
target.mode_info = &framebuffer.render_target->mode_info;
|
||||
target.data = framebuffer.render_target->data;
|
||||
|
||||
/* Do actual blitting. */
|
||||
common_blitter (&target, &source, oper, x, y, width, height,
|
||||
|
@ -852,9 +873,9 @@ grub_video_fb_blit_render_target (struct grub_video_fbrender_target *source,
|
|||
/* 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 >= (int)framebuffer.render_target->viewport.width) || (x + (int)width < 0))
|
||||
return GRUB_ERR_NONE;
|
||||
if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0))
|
||||
if ((y >= (int)framebuffer.render_target->viewport.height) || (y + (int)height < 0))
|
||||
return GRUB_ERR_NONE;
|
||||
if ((x + (int)source->mode_info.width) < 0)
|
||||
return GRUB_ERR_NONE;
|
||||
|
@ -897,10 +918,10 @@ grub_video_fb_blit_render_target (struct grub_video_fbrender_target *source,
|
|||
}
|
||||
|
||||
/* Do not allow drawing out of viewport. */
|
||||
if ((x + width) > render_target->viewport.width)
|
||||
width = render_target->viewport.width - x;
|
||||
if ((y + height) > render_target->viewport.height)
|
||||
height = render_target->viewport.height - y;
|
||||
if ((x + width) > framebuffer.render_target->viewport.width)
|
||||
width = framebuffer.render_target->viewport.width - x;
|
||||
if ((y + height) > framebuffer.render_target->viewport.height)
|
||||
height = framebuffer.render_target->viewport.height - y;
|
||||
|
||||
if ((offset_x + width) > source->mode_info.width)
|
||||
width = source->mode_info.width - offset_x;
|
||||
|
@ -915,14 +936,14 @@ grub_video_fb_blit_render_target (struct grub_video_fbrender_target *source,
|
|||
height = source->mode_info.height;
|
||||
|
||||
/* Add viewport offset. */
|
||||
x += render_target->viewport.x;
|
||||
y += render_target->viewport.y;
|
||||
x += framebuffer.render_target->viewport.x;
|
||||
y += framebuffer.render_target->viewport.y;
|
||||
|
||||
/* Use fbblit_info to encapsulate rendering. */
|
||||
source_info.mode_info = &source->mode_info;
|
||||
source_info.data = source->data;
|
||||
target_info.mode_info = &render_target->mode_info;
|
||||
target_info.data = render_target->data;
|
||||
target_info.mode_info = &framebuffer.render_target->mode_info;
|
||||
target_info.data = framebuffer.render_target->data;
|
||||
|
||||
/* Do actual blitting. */
|
||||
common_blitter (&target_info, &source_info, oper, x, y, width, height,
|
||||
|
@ -945,42 +966,42 @@ grub_video_fb_scroll (grub_video_color_t color, int dx, int dy)
|
|||
if ((dx == 0) && (dy == 0))
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
width = render_target->viewport.width - grub_abs (dx);
|
||||
height = render_target->viewport.height - grub_abs (dy);
|
||||
width = framebuffer.render_target->viewport.width - grub_abs (dx);
|
||||
height = framebuffer.render_target->viewport.height - grub_abs (dy);
|
||||
|
||||
if (dx < 0)
|
||||
{
|
||||
src_x = render_target->viewport.x - dx;
|
||||
dst_x = render_target->viewport.x;
|
||||
src_x = framebuffer.render_target->viewport.x - dx;
|
||||
dst_x = framebuffer.render_target->viewport.x;
|
||||
}
|
||||
else
|
||||
{
|
||||
src_x = render_target->viewport.x;
|
||||
dst_x = render_target->viewport.x + dx;
|
||||
src_x = framebuffer.render_target->viewport.x;
|
||||
dst_x = framebuffer.render_target->viewport.x + dx;
|
||||
}
|
||||
|
||||
if (dy < 0)
|
||||
{
|
||||
src_y = render_target->viewport.y - dy;
|
||||
dst_y = render_target->viewport.y;
|
||||
src_y = framebuffer.render_target->viewport.y - dy;
|
||||
dst_y = framebuffer.render_target->viewport.y;
|
||||
}
|
||||
else
|
||||
{
|
||||
src_y = render_target->viewport.y;
|
||||
dst_y = render_target->viewport.y + dy;
|
||||
src_y = framebuffer.render_target->viewport.y;
|
||||
dst_y = framebuffer.render_target->viewport.y + dy;
|
||||
}
|
||||
|
||||
/* 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 ((grub_abs (dx) < framebuffer.render_target->viewport.width)
|
||||
&& (grub_abs (dy) < framebuffer.render_target->viewport.height))
|
||||
{
|
||||
/* 3. Move data in render target. */
|
||||
struct grub_video_fbblit_info target;
|
||||
int i, j;
|
||||
int linedelta, linelen;
|
||||
|
||||
target.mode_info = &render_target->mode_info;
|
||||
target.data = render_target->data;
|
||||
target.mode_info = &framebuffer.render_target->mode_info;
|
||||
target.data = framebuffer.render_target->data;
|
||||
|
||||
linedelta = target.mode_info->pitch
|
||||
- width * target.mode_info->bytes_per_pixel;
|
||||
|
@ -1063,27 +1084,27 @@ grub_video_fb_scroll (grub_video_color_t color, int dx, int dy)
|
|||
|
||||
/* 4a. Fill top & bottom parts. */
|
||||
if (dy > 0)
|
||||
grub_video_fb_fill_rect (color, 0, 0, render_target->viewport.width, dy);
|
||||
grub_video_fb_fill_rect (color, 0, 0, framebuffer.render_target->viewport.width, dy);
|
||||
else if (dy < 0)
|
||||
{
|
||||
if (render_target->viewport.height < grub_abs (dy))
|
||||
dy = -render_target->viewport.height;
|
||||
if (framebuffer.render_target->viewport.height < grub_abs (dy))
|
||||
dy = -framebuffer.render_target->viewport.height;
|
||||
|
||||
grub_video_fb_fill_rect (color, 0, render_target->viewport.height + dy,
|
||||
render_target->viewport.width, -dy);
|
||||
grub_video_fb_fill_rect (color, 0, framebuffer.render_target->viewport.height + dy,
|
||||
framebuffer.render_target->viewport.width, -dy);
|
||||
}
|
||||
|
||||
/* 4b. Fill left & right parts. */
|
||||
if (dx > 0)
|
||||
grub_video_fb_fill_rect (color, 0, 0,
|
||||
dx, render_target->viewport.height);
|
||||
dx, framebuffer.render_target->viewport.height);
|
||||
else if (dx < 0)
|
||||
{
|
||||
if (render_target->viewport.width < grub_abs (dx))
|
||||
dx = -render_target->viewport.width;
|
||||
if (framebuffer.render_target->viewport.width < grub_abs (dx))
|
||||
dx = -framebuffer.render_target->viewport.width;
|
||||
|
||||
grub_video_fb_fill_rect (color, render_target->viewport.width + dx, 0,
|
||||
-dx, render_target->viewport.height);
|
||||
grub_video_fb_fill_rect (color, framebuffer.render_target->viewport.width + dx, 0,
|
||||
-dx, framebuffer.render_target->viewport.height);
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
|
@ -1130,7 +1151,7 @@ grub_video_fb_create_render_target (struct grub_video_fbrender_target **result,
|
|||
target->mode_info.bpp = 32;
|
||||
target->mode_info.bytes_per_pixel = 4;
|
||||
target->mode_info.pitch = target->mode_info.bytes_per_pixel * width;
|
||||
target->mode_info.number_of_colors = palette_size; /* Emulated palette. */
|
||||
target->mode_info.number_of_colors = framebuffer.palette_size; /* Emulated palette. */
|
||||
target->mode_info.red_mask_size = 8;
|
||||
target->mode_info.red_field_pos = 0;
|
||||
target->mode_info.green_mask_size = 8;
|
||||
|
@ -1221,11 +1242,15 @@ grub_video_fb_delete_render_target (struct grub_video_fbrender_target *target)
|
|||
grub_err_t
|
||||
grub_video_fb_set_active_render_target (struct grub_video_fbrender_target *target)
|
||||
{
|
||||
if (target == (struct grub_video_fbrender_target *)
|
||||
GRUB_VIDEO_RENDER_TARGET_DISPLAY)
|
||||
target = framebuffer.back_target;
|
||||
|
||||
if (! target->data)
|
||||
return grub_error (GRUB_ERR_BAD_ARGUMENT,
|
||||
"invalid render target given");
|
||||
|
||||
render_target = target;
|
||||
framebuffer.render_target = target;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
@ -1233,7 +1258,10 @@ grub_video_fb_set_active_render_target (struct grub_video_fbrender_target *targe
|
|||
grub_err_t
|
||||
grub_video_fb_get_active_render_target (struct grub_video_fbrender_target **target)
|
||||
{
|
||||
*target = render_target;
|
||||
*target = framebuffer.render_target;
|
||||
|
||||
if (*target == framebuffer.back_target)
|
||||
*target = (struct grub_video_fbrender_target *) GRUB_VIDEO_RENDER_TARGET_DISPLAY;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
@ -1247,24 +1275,22 @@ doublebuf_blit_update_screen (struct grub_video_fbrender_target *front,
|
|||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
static grub_err_t
|
||||
grub_video_fb_doublebuf_blit_init (struct grub_video_fbrender_target **front,
|
||||
struct grub_video_fbrender_target **back,
|
||||
grub_video_fb_doublebuf_update_screen_t *update_screen,
|
||||
struct grub_video_mode_info mode_info,
|
||||
void *framebuf)
|
||||
{
|
||||
grub_err_t err;
|
||||
int page_size = mode_info.pitch * mode_info.height;
|
||||
void *offscreen_buffer;
|
||||
|
||||
err = grub_video_fb_create_render_target_from_pointer (front, &mode_info,
|
||||
framebuf);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
offscreen_buffer = grub_malloc (page_size);
|
||||
if (! offscreen_buffer)
|
||||
framebuffer.offscreen_buffer = grub_malloc (page_size);
|
||||
if (! framebuffer.offscreen_buffer)
|
||||
{
|
||||
grub_video_fb_delete_render_target (*front);
|
||||
*front = 0;
|
||||
|
@ -1272,18 +1298,216 @@ grub_video_fb_doublebuf_blit_init (struct grub_video_fbrender_target **front,
|
|||
}
|
||||
|
||||
err = grub_video_fb_create_render_target_from_pointer (back, &mode_info,
|
||||
offscreen_buffer);
|
||||
framebuffer.offscreen_buffer);
|
||||
|
||||
if (err)
|
||||
{
|
||||
grub_video_fb_delete_render_target (*front);
|
||||
grub_free (offscreen_buffer);
|
||||
grub_free (framebuffer.offscreen_buffer);
|
||||
framebuffer.offscreen_buffer = 0;
|
||||
*front = 0;
|
||||
return grub_errno;
|
||||
}
|
||||
(*back)->is_allocated = 1;
|
||||
|
||||
*update_screen = doublebuf_blit_update_screen;
|
||||
framebuffer.update_screen = doublebuf_blit_update_screen;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
doublebuf_pageflipping_update_screen (struct grub_video_fbrender_target *front
|
||||
__attribute__ ((unused)),
|
||||
struct grub_video_fbrender_target *back
|
||||
__attribute__ ((unused)))
|
||||
{
|
||||
int new_displayed_page;
|
||||
struct grub_video_fbrender_target *target;
|
||||
grub_err_t err;
|
||||
|
||||
/* Swap the page numbers in the framebuffer struct. */
|
||||
new_displayed_page = framebuffer.render_page;
|
||||
framebuffer.render_page = framebuffer.displayed_page;
|
||||
framebuffer.displayed_page = new_displayed_page;
|
||||
|
||||
err = framebuffer.set_page (framebuffer.displayed_page);
|
||||
if (err)
|
||||
{
|
||||
/* Restore previous state. */
|
||||
framebuffer.render_page = framebuffer.displayed_page;
|
||||
framebuffer.displayed_page = new_displayed_page;
|
||||
return err;
|
||||
}
|
||||
|
||||
target = framebuffer.back_target;
|
||||
framebuffer.back_target = framebuffer.front_target;
|
||||
framebuffer.front_target = target;
|
||||
|
||||
if (framebuffer.front_target->mode_info.mode_type
|
||||
& GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP)
|
||||
grub_memcpy (framebuffer.back_target->data, framebuffer.front_target->data,
|
||||
framebuffer.back_target->mode_info.pitch
|
||||
* framebuffer.back_target->mode_info.height);
|
||||
|
||||
err = grub_video_fb_get_active_render_target (&target);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (framebuffer.render_target == framebuffer.back_target)
|
||||
framebuffer.render_target = framebuffer.front_target;
|
||||
else if (framebuffer.render_target == framebuffer.front_target)
|
||||
framebuffer.render_target = framebuffer.back_target;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
doublebuf_pageflipping_init (struct grub_video_mode_info *mode_info,
|
||||
volatile void *page0_ptr,
|
||||
grub_video_fb_set_page_t set_page_in,
|
||||
volatile void *page1_ptr)
|
||||
{
|
||||
grub_err_t err;
|
||||
|
||||
framebuffer.displayed_page = 0;
|
||||
framebuffer.render_page = 1;
|
||||
|
||||
framebuffer.update_screen = doublebuf_pageflipping_update_screen;
|
||||
|
||||
err = grub_video_fb_create_render_target_from_pointer (&framebuffer.front_target,
|
||||
mode_info,
|
||||
(void *) page0_ptr);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = grub_video_fb_create_render_target_from_pointer (&framebuffer.back_target,
|
||||
mode_info,
|
||||
(void *) page1_ptr);
|
||||
if (err)
|
||||
{
|
||||
grub_video_fb_delete_render_target (framebuffer.front_target);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Set the framebuffer memory data pointer and display the right page. */
|
||||
err = set_page_in (framebuffer.displayed_page);
|
||||
if (err)
|
||||
{
|
||||
grub_video_fb_delete_render_target (framebuffer.front_target);
|
||||
grub_video_fb_delete_render_target (framebuffer.back_target);
|
||||
return err;
|
||||
}
|
||||
framebuffer.set_page = set_page_in;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Select the best double buffering mode available. */
|
||||
grub_err_t
|
||||
grub_video_fb_setup (unsigned int mode_type, unsigned int mode_mask,
|
||||
struct grub_video_mode_info *mode_info,
|
||||
volatile void *page0_ptr,
|
||||
grub_video_fb_set_page_t set_page_in,
|
||||
volatile void *page1_ptr)
|
||||
{
|
||||
grub_err_t err;
|
||||
int updating_swap_needed;
|
||||
|
||||
updating_swap_needed
|
||||
= grub_video_check_mode_flag (mode_type, mode_mask,
|
||||
GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP, 0);
|
||||
|
||||
/* Do double buffering only if it's either requested or efficient. */
|
||||
if (set_page_in && grub_video_check_mode_flag (mode_type, mode_mask,
|
||||
GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED,
|
||||
!updating_swap_needed))
|
||||
{
|
||||
mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
|
||||
if (updating_swap_needed)
|
||||
mode_info->mode_type |= GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP;
|
||||
|
||||
err = doublebuf_pageflipping_init (mode_info, page0_ptr,
|
||||
set_page_in,
|
||||
page1_ptr);
|
||||
if (!err)
|
||||
{
|
||||
framebuffer.render_target = framebuffer.back_target;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
mode_info->mode_type &= ~(GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
|
||||
| GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
|
||||
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
if (grub_video_check_mode_flag (mode_type, mode_mask,
|
||||
GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED,
|
||||
0))
|
||||
{
|
||||
mode_info->mode_type |= (GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
|
||||
| GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
|
||||
|
||||
err = grub_video_fb_doublebuf_blit_init (&framebuffer.front_target,
|
||||
&framebuffer.back_target,
|
||||
*mode_info,
|
||||
(void *) page0_ptr);
|
||||
|
||||
if (!err)
|
||||
{
|
||||
framebuffer.render_target = framebuffer.back_target;
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
mode_info->mode_type &= ~(GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
|
||||
| GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
|
||||
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Fall back to no double buffering. */
|
||||
err = grub_video_fb_create_render_target_from_pointer (&framebuffer.front_target,
|
||||
mode_info,
|
||||
(void *) page0_ptr);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
framebuffer.back_target = framebuffer.front_target;
|
||||
framebuffer.update_screen = 0;
|
||||
|
||||
mode_info->mode_type &= ~GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
|
||||
|
||||
framebuffer.render_target = framebuffer.back_target;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
grub_err_t
|
||||
grub_video_fb_swap_buffers (void)
|
||||
{
|
||||
grub_err_t err;
|
||||
if (!framebuffer.update_screen)
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
err = framebuffer.update_screen (framebuffer.front_target,
|
||||
framebuffer.back_target);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
grub_err_t
|
||||
grub_video_fb_get_info_and_fini (struct grub_video_mode_info *mode_info,
|
||||
void **framebuf)
|
||||
{
|
||||
grub_memcpy (mode_info, &(framebuffer.front_target->mode_info),
|
||||
sizeof (*mode_info));
|
||||
*framebuf = framebuffer.front_target->data;
|
||||
|
||||
grub_video_fb_fini ();
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
|
|
@ -40,25 +40,12 @@ static grub_uint32_t last_set_mode = 3;
|
|||
static struct
|
||||
{
|
||||
struct grub_video_mode_info mode_info;
|
||||
struct grub_video_render_target *front_target;
|
||||
struct grub_video_render_target *back_target;
|
||||
|
||||
unsigned int bytes_per_scan_line;
|
||||
unsigned int bytes_per_pixel;
|
||||
grub_uint32_t active_vbe_mode;
|
||||
grub_uint8_t *ptr;
|
||||
int index_color_mode;
|
||||
|
||||
char *offscreen_buffer;
|
||||
|
||||
grub_size_t page_size; /* The size of a page in bytes. */
|
||||
|
||||
/* For page flipping strategy. */
|
||||
int displayed_page; /* The page # that is the front buffer. */
|
||||
int render_page; /* The page # that is the back buffer. */
|
||||
|
||||
/* Virtual functions. */
|
||||
grub_video_fb_doublebuf_update_screen_t update_screen;
|
||||
} framebuffer;
|
||||
|
||||
static grub_uint32_t initial_vbe_mode;
|
||||
|
@ -377,7 +364,6 @@ grub_video_vbe_fini (void)
|
|||
vbe_mode_list = NULL;
|
||||
|
||||
err = grub_video_fb_fini ();
|
||||
grub_free (framebuffer.offscreen_buffer);
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -387,11 +373,11 @@ grub_video_vbe_fini (void)
|
|||
respectively.
|
||||
*/
|
||||
static grub_err_t
|
||||
doublebuf_pageflipping_commit (void)
|
||||
doublebuf_pageflipping_set_page (int page)
|
||||
{
|
||||
/* Tell the video adapter to display the new front page. */
|
||||
int display_start_line
|
||||
= framebuffer.mode_info.height * framebuffer.displayed_page;
|
||||
= framebuffer.mode_info.height * page;
|
||||
|
||||
grub_vbe_status_t vbe_err =
|
||||
grub_vbe_bios_set_display_start (0, display_start_line);
|
||||
|
@ -402,164 +388,6 @@ doublebuf_pageflipping_commit (void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
doublebuf_pageflipping_update_screen (struct grub_video_fbrender_target *front
|
||||
__attribute__ ((unused)),
|
||||
struct grub_video_fbrender_target *back
|
||||
__attribute__ ((unused)))
|
||||
{
|
||||
int new_displayed_page;
|
||||
struct grub_video_fbrender_target *target;
|
||||
grub_err_t err;
|
||||
|
||||
/* Swap the page numbers in the framebuffer struct. */
|
||||
new_displayed_page = framebuffer.render_page;
|
||||
framebuffer.render_page = framebuffer.displayed_page;
|
||||
framebuffer.displayed_page = new_displayed_page;
|
||||
|
||||
err = doublebuf_pageflipping_commit ();
|
||||
if (err)
|
||||
{
|
||||
/* Restore previous state. */
|
||||
framebuffer.render_page = framebuffer.displayed_page;
|
||||
framebuffer.displayed_page = new_displayed_page;
|
||||
return err;
|
||||
}
|
||||
|
||||
if (framebuffer.mode_info.mode_type & GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP)
|
||||
grub_memcpy (framebuffer.ptr + framebuffer.render_page
|
||||
* framebuffer.page_size, framebuffer.ptr
|
||||
+ framebuffer.displayed_page * framebuffer.page_size,
|
||||
framebuffer.page_size);
|
||||
|
||||
target = framebuffer.back_target;
|
||||
framebuffer.back_target = framebuffer.front_target;
|
||||
framebuffer.front_target = target;
|
||||
|
||||
err = grub_video_fb_get_active_render_target (&target);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (target == framebuffer.back_target)
|
||||
err = grub_video_fb_set_active_render_target (framebuffer.front_target);
|
||||
else if (target == framebuffer.front_target)
|
||||
err = grub_video_fb_set_active_render_target (framebuffer.back_target);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
doublebuf_pageflipping_init (void)
|
||||
{
|
||||
/* Get video RAM size in bytes. */
|
||||
grub_size_t vram_size = controller_info.total_memory << 16;
|
||||
grub_err_t err;
|
||||
|
||||
framebuffer.page_size =
|
||||
framebuffer.mode_info.pitch * framebuffer.mode_info.height;
|
||||
|
||||
if (2 * framebuffer.page_size > vram_size)
|
||||
return grub_error (GRUB_ERR_OUT_OF_MEMORY,
|
||||
"Not enough video memory for double buffering.");
|
||||
|
||||
framebuffer.displayed_page = 0;
|
||||
framebuffer.render_page = 1;
|
||||
|
||||
framebuffer.update_screen = doublebuf_pageflipping_update_screen;
|
||||
|
||||
err = grub_video_fb_create_render_target_from_pointer (&framebuffer.front_target, &framebuffer.mode_info, framebuffer.ptr);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
err = grub_video_fb_create_render_target_from_pointer (&framebuffer.back_target, &framebuffer.mode_info, framebuffer.ptr + framebuffer.page_size);
|
||||
if (err)
|
||||
{
|
||||
grub_video_fb_delete_render_target (framebuffer.front_target);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Set the framebuffer memory data pointer and display the right page. */
|
||||
err = doublebuf_pageflipping_commit ();
|
||||
if (err)
|
||||
{
|
||||
grub_video_fb_delete_render_target (framebuffer.front_target);
|
||||
grub_video_fb_delete_render_target (framebuffer.back_target);
|
||||
return err;
|
||||
}
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Select the best double buffering mode available. */
|
||||
static grub_err_t
|
||||
double_buffering_init (unsigned int mode_type, unsigned int mode_mask)
|
||||
{
|
||||
grub_err_t err;
|
||||
int updating_swap_needed;
|
||||
|
||||
updating_swap_needed
|
||||
= grub_video_check_mode_flag (mode_type, mode_mask,
|
||||
GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP, 0);
|
||||
|
||||
/* Do double buffering only if it's either requested or efficient. */
|
||||
if (grub_video_check_mode_flag (mode_type, mode_mask,
|
||||
GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED,
|
||||
!updating_swap_needed))
|
||||
{
|
||||
framebuffer.mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
|
||||
if (updating_swap_needed)
|
||||
framebuffer.mode_info.mode_type |= GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP;
|
||||
err = doublebuf_pageflipping_init ();
|
||||
if (!err)
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
framebuffer.mode_info.mode_type
|
||||
&= ~(GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
|
||||
| GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
|
||||
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
if (grub_video_check_mode_flag (mode_type, mode_mask,
|
||||
GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED,
|
||||
0))
|
||||
{
|
||||
framebuffer.mode_info.mode_type
|
||||
|= (GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
|
||||
| GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
|
||||
|
||||
err = grub_video_fb_doublebuf_blit_init (&framebuffer.front_target,
|
||||
&framebuffer.back_target,
|
||||
&framebuffer.update_screen,
|
||||
framebuffer.mode_info,
|
||||
framebuffer.ptr);
|
||||
|
||||
if (!err)
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
framebuffer.mode_info.mode_type
|
||||
&= ~(GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED
|
||||
| GRUB_VIDEO_MODE_TYPE_UPDATING_SWAP);
|
||||
|
||||
grub_errno = GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
/* Fall back to no double buffering. */
|
||||
err = grub_video_fb_create_render_target_from_pointer (&framebuffer.front_target, &framebuffer.mode_info, framebuffer.ptr);
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
framebuffer.back_target = framebuffer.front_target;
|
||||
framebuffer.update_screen = 0;
|
||||
|
||||
framebuffer.mode_info.mode_type &= ~GRUB_VIDEO_MODE_TYPE_DOUBLE_BUFFERED;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static grub_err_t
|
||||
grub_video_vbe_setup (unsigned int width, unsigned int height,
|
||||
unsigned int mode_type, unsigned int mode_mask)
|
||||
|
@ -684,15 +512,24 @@ grub_video_vbe_setup (unsigned int width, unsigned int height,
|
|||
|
||||
framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info);
|
||||
|
||||
/* Set up double buffering and targets. */
|
||||
err = double_buffering_init (mode_type, mode_mask);
|
||||
if (err)
|
||||
return err;
|
||||
{
|
||||
/* Get video RAM size in bytes. */
|
||||
grub_size_t vram_size = controller_info.total_memory << 16;
|
||||
grub_size_t page_size; /* The size of a page in bytes. */
|
||||
|
||||
err = grub_video_fb_set_active_render_target (framebuffer.back_target);
|
||||
page_size = framebuffer.mode_info.pitch * framebuffer.mode_info.height;
|
||||
|
||||
if (err)
|
||||
return err;
|
||||
if (vram_size >= 2 * page_size)
|
||||
err = grub_video_fb_setup (mode_type, mode_mask,
|
||||
&framebuffer.mode_info,
|
||||
framebuffer.ptr,
|
||||
doublebuf_pageflipping_set_page,
|
||||
framebuffer.ptr + page_size);
|
||||
else
|
||||
err = grub_video_fb_setup (mode_type, mode_mask,
|
||||
&framebuffer.mode_info,
|
||||
framebuffer.ptr, 0, 0);
|
||||
}
|
||||
|
||||
/* Copy default palette to initialize emulated palette. */
|
||||
err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
|
||||
|
@ -723,59 +560,13 @@ grub_video_vbe_set_palette (unsigned int start, unsigned int count,
|
|||
return grub_video_fb_set_palette (start, count, palette_data);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_video_vbe_swap_buffers (void)
|
||||
{
|
||||
grub_err_t err;
|
||||
if (!framebuffer.update_screen)
|
||||
return GRUB_ERR_NONE;
|
||||
|
||||
err = framebuffer.update_screen (framebuffer.front_target,
|
||||
framebuffer.back_target);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_video_vbe_set_active_render_target (struct grub_video_render_target *target)
|
||||
{
|
||||
if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY)
|
||||
target = framebuffer.back_target;
|
||||
|
||||
return grub_video_fb_set_active_render_target (target);
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_video_vbe_get_active_render_target (struct grub_video_render_target **target)
|
||||
{
|
||||
grub_err_t err;
|
||||
err = grub_video_fb_get_active_render_target (target);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (*target == framebuffer.back_target)
|
||||
*target = GRUB_VIDEO_RENDER_TARGET_DISPLAY;
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
}
|
||||
|
||||
static grub_err_t
|
||||
grub_video_vbe_get_info_and_fini (struct grub_video_mode_info *mode_info,
|
||||
void **framebuf)
|
||||
{
|
||||
grub_memcpy (mode_info, &(framebuffer.mode_info), sizeof (*mode_info));
|
||||
*framebuf = (char *) framebuffer.ptr
|
||||
+ framebuffer.displayed_page * framebuffer.page_size;
|
||||
|
||||
grub_free (vbe_mode_list);
|
||||
vbe_mode_list = NULL;
|
||||
|
||||
grub_video_fb_fini ();
|
||||
grub_free (framebuffer.offscreen_buffer);
|
||||
|
||||
return GRUB_ERR_NONE;
|
||||
return grub_video_fb_get_info_and_fini (mode_info, framebuf);
|
||||
}
|
||||
|
||||
static struct grub_video_adapter grub_video_vbe_adapter =
|
||||
|
@ -802,11 +593,11 @@ static struct grub_video_adapter grub_video_vbe_adapter =
|
|||
.blit_bitmap = grub_video_fb_blit_bitmap,
|
||||
.blit_render_target = grub_video_fb_blit_render_target,
|
||||
.scroll = grub_video_fb_scroll,
|
||||
.swap_buffers = grub_video_vbe_swap_buffers,
|
||||
.swap_buffers = grub_video_fb_swap_buffers,
|
||||
.create_render_target = grub_video_fb_create_render_target,
|
||||
.delete_render_target = grub_video_fb_delete_render_target,
|
||||
.set_active_render_target = grub_video_vbe_set_active_render_target,
|
||||
.get_active_render_target = grub_video_vbe_get_active_render_target,
|
||||
.set_active_render_target = grub_video_fb_set_active_render_target,
|
||||
.get_active_render_target = grub_video_fb_get_active_render_target,
|
||||
|
||||
.next = 0
|
||||
};
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <grub/types.h>
|
||||
#include <grub/dl.h>
|
||||
#include <grub/misc.h>
|
||||
#include <grub/vga.h>
|
||||
|
||||
#define VGA_WIDTH 640
|
||||
#define VGA_HEIGHT 350
|
||||
|
@ -45,58 +46,26 @@ static struct
|
|||
int back_page;
|
||||
} framebuffer;
|
||||
|
||||
#define SEQUENCER_ADDR_PORT 0x3C4
|
||||
#define SEQUENCER_DATA_PORT 0x3C5
|
||||
#define MAP_MASK_REGISTER 0x02
|
||||
|
||||
#define CRTC_ADDR_PORT 0x3D4
|
||||
#define CRTC_DATA_PORT 0x3D5
|
||||
#define START_ADDR_HIGH_REGISTER 0x0C
|
||||
#define START_ADDR_LOW_REGISTER 0x0D
|
||||
|
||||
#define GRAPHICS_ADDR_PORT 0x3CE
|
||||
#define GRAPHICS_DATA_PORT 0x3CF
|
||||
#define READ_MAP_REGISTER 0x04
|
||||
|
||||
#define INPUT_STATUS1_REGISTER 0x3DA
|
||||
#define INPUT_STATUS1_VERTR_BIT 0x08
|
||||
|
||||
static inline void
|
||||
wait_vretrace (void)
|
||||
{
|
||||
/* Wait until there is a vertical retrace. */
|
||||
while (! (grub_inb (INPUT_STATUS1_REGISTER) & INPUT_STATUS1_VERTR_BIT));
|
||||
while (! (grub_inb (GRUB_VGA_IO_INPUT_STATUS1_REGISTER)
|
||||
& GRUB_VGA_IO_INPUT_STATUS1_VERTR_BIT));
|
||||
}
|
||||
|
||||
/* Get Map Mask Register. */
|
||||
static unsigned char
|
||||
get_map_mask (void)
|
||||
{
|
||||
unsigned char old_addr;
|
||||
unsigned char old_data;
|
||||
|
||||
old_addr = grub_inb (SEQUENCER_ADDR_PORT);
|
||||
grub_outb (MAP_MASK_REGISTER, SEQUENCER_ADDR_PORT);
|
||||
|
||||
old_data = grub_inb (SEQUENCER_DATA_PORT);
|
||||
|
||||
grub_outb (old_addr, SEQUENCER_ADDR_PORT);
|
||||
|
||||
return old_data;
|
||||
return grub_vga_sr_read (GRUB_VGA_SR_MAP_MASK_REGISTER);
|
||||
}
|
||||
|
||||
/* Set Map Mask Register. */
|
||||
static void
|
||||
set_map_mask (unsigned char mask)
|
||||
{
|
||||
unsigned char old_addr;
|
||||
|
||||
old_addr = grub_inb (SEQUENCER_ADDR_PORT);
|
||||
grub_outb (MAP_MASK_REGISTER, SEQUENCER_ADDR_PORT);
|
||||
|
||||
grub_outb (mask, SEQUENCER_DATA_PORT);
|
||||
|
||||
grub_outb (old_addr, SEQUENCER_ADDR_PORT);
|
||||
grub_vga_sr_write (mask, GRUB_VGA_SR_MAP_MASK_REGISTER);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
@ -104,14 +73,7 @@ set_map_mask (unsigned char mask)
|
|||
static void
|
||||
set_read_map (unsigned char map)
|
||||
{
|
||||
unsigned char old_addr;
|
||||
|
||||
old_addr = grub_inb (GRAPHICS_ADDR_PORT);
|
||||
|
||||
grub_outb (READ_MAP_REGISTER, GRAPHICS_ADDR_PORT);
|
||||
grub_outb (map, GRAPHICS_DATA_PORT);
|
||||
|
||||
grub_outb (old_addr, GRAPHICS_ADDR_PORT);
|
||||
grub_vga_gr_write (map, GRUB_VGA_GR_READ_MAP_REGISTER);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -119,17 +81,8 @@ set_read_map (unsigned char map)
|
|||
static void
|
||||
set_start_address (unsigned int start)
|
||||
{
|
||||
unsigned char old_addr;
|
||||
|
||||
old_addr = grub_inb (CRTC_ADDR_PORT);
|
||||
|
||||
grub_outb (START_ADDR_LOW_REGISTER, CRTC_ADDR_PORT);
|
||||
grub_outb (start & 0xFF, CRTC_DATA_PORT);
|
||||
|
||||
grub_outb (START_ADDR_HIGH_REGISTER, CRTC_ADDR_PORT);
|
||||
grub_outb (start >> 8, CRTC_DATA_PORT);
|
||||
|
||||
grub_outb (old_addr, CRTC_ADDR_PORT);
|
||||
grub_vga_cr_write (start & 0xFF, GRUB_VGA_CR_START_ADDR_LOW_REGISTER);
|
||||
grub_vga_cr_write (start >> 8, GRUB_VGA_CR_START_ADDR_HIGH_REGISTER);
|
||||
}
|
||||
|
||||
static int setup = 0;
|
||||
|
|
|
@ -32,10 +32,7 @@ static struct
|
|||
struct grub_video_mode_info mode_info;
|
||||
struct grub_video_render_target *render_target;
|
||||
|
||||
unsigned int bytes_per_scan_line;
|
||||
unsigned int bytes_per_pixel;
|
||||
grub_uint8_t *ptr;
|
||||
int index_color_mode;
|
||||
int mapped;
|
||||
grub_uint32_t base;
|
||||
grub_pci_device_t dev;
|
||||
|
|
Loading…
Reference in a new issue