merge mainline into emu-mod

This commit is contained in:
Vladimir 'phcoder' Serbinenko 2010-02-07 03:06:33 +01:00
commit 19a9fb834b
459 changed files with 26481 additions and 7640 deletions

View file

@ -58,12 +58,12 @@ grub_video_bitmap_create (struct grub_video_bitmap **bitmap,
unsigned int size;
if (!bitmap)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid argument.");
return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument");
*bitmap = 0;
if (width == 0 || height == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid argument.");
return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument");
*bitmap = (struct grub_video_bitmap *)grub_malloc (sizeof (struct grub_video_bitmap));
if (! *bitmap)
@ -129,7 +129,7 @@ grub_video_bitmap_create (struct grub_video_bitmap **bitmap,
*bitmap = 0;
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"Unsupported bitmap format");
"unsupported bitmap format");
}
mode_info->pitch = width * mode_info->bytes_per_pixel;
@ -188,7 +188,7 @@ grub_video_bitmap_load (struct grub_video_bitmap **bitmap,
grub_video_bitmap_reader_t reader = bitmap_readers_list;
if (!bitmap)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid argument.");
return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument");
*bitmap = 0;

308
video/bitmap_scale.c Normal file
View file

@ -0,0 +1,308 @@
/* bitmap_scale.c - Bitmap scaling. */
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2006,2007,2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* GRUB is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GRUB. If not, see <http://www.gnu.org/licenses/>.
*/
#include <grub/mm.h>
#include <grub/misc.h>
#include <grub/video.h>
#include <grub/bitmap.h>
#include <grub/bitmap_scale.h>
#include <grub/types.h>
/* Prototypes for module-local functions. */
static grub_err_t scale_nn (struct grub_video_bitmap *dst,
struct grub_video_bitmap *src);
static grub_err_t scale_bilinear (struct grub_video_bitmap *dst,
struct grub_video_bitmap *src);
/* This function creates a new scaled version of the bitmap SRC. The new
bitmap has dimensions DST_WIDTH by DST_HEIGHT. The scaling algorithm
is given by SCALE_METHOD. If an error is encountered, the return code is
not equal to GRUB_ERR_NONE, and the bitmap DST is either not created, or
it is destroyed before this function returns.
Supports only direct color modes which have components separated
into bytes (e.g., RGBA 8:8:8:8 or BGR 8:8:8 true color).
But because of this simplifying assumption, the implementation is
greatly simplified. */
grub_err_t
grub_video_bitmap_create_scaled (struct grub_video_bitmap **dst,
int dst_width, int dst_height,
struct grub_video_bitmap *src,
enum grub_video_bitmap_scale_method
scale_method)
{
*dst = 0;
/* Verify the simplifying assumptions. */
if (src == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"null src bitmap in grub_video_bitmap_create_scaled");
if (src->mode_info.red_field_pos % 8 != 0
|| src->mode_info.green_field_pos % 8 != 0
|| src->mode_info.blue_field_pos % 8 != 0
|| src->mode_info.reserved_field_pos % 8 != 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"src format not supported for scale");
if (src->mode_info.width == 0 || src->mode_info.height == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"source bitmap has a zero dimension");
if (dst_width <= 0 || dst_height <= 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"requested to scale to a size w/ a zero dimension");
if (src->mode_info.bytes_per_pixel * 8 != src->mode_info.bpp)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"bitmap to scale has inconsistent Bpp and bpp");
/* Create the new bitmap. */
grub_err_t ret;
ret = grub_video_bitmap_create (dst, dst_width, dst_height,
src->mode_info.blit_format);
if (ret != GRUB_ERR_NONE)
return ret; /* Error. */
switch (scale_method)
{
case GRUB_VIDEO_BITMAP_SCALE_METHOD_FASTEST:
case GRUB_VIDEO_BITMAP_SCALE_METHOD_NEAREST:
ret = scale_nn (*dst, src);
break;
case GRUB_VIDEO_BITMAP_SCALE_METHOD_BEST:
case GRUB_VIDEO_BITMAP_SCALE_METHOD_BILINEAR:
ret = scale_bilinear (*dst, src);
break;
default:
ret = grub_error (GRUB_ERR_BAD_ARGUMENT, "Invalid scale_method value");
break;
}
if (ret == GRUB_ERR_NONE)
{
/* Success: *dst is now a pointer to the scaled bitmap. */
return GRUB_ERR_NONE;
}
else
{
/* Destroy the bitmap and return the error code. */
grub_video_bitmap_destroy (*dst);
*dst = 0;
return ret;
}
}
/* Nearest neighbor bitmap scaling algorithm.
Copy the bitmap SRC to the bitmap DST, scaling the bitmap to fit the
dimensions of DST. This function uses the nearest neighbor algorithm to
interpolate the pixels.
Supports only direct color modes which have components separated
into bytes (e.g., RGBA 8:8:8:8 or BGR 8:8:8 true color).
But because of this simplifying assumption, the implementation is
greatly simplified. */
static grub_err_t
scale_nn (struct grub_video_bitmap *dst, struct grub_video_bitmap *src)
{
/* Verify the simplifying assumptions. */
if (dst == 0 || src == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "null bitmap in scale_nn");
if (dst->mode_info.red_field_pos % 8 != 0
|| dst->mode_info.green_field_pos % 8 != 0
|| dst->mode_info.blue_field_pos % 8 != 0
|| dst->mode_info.reserved_field_pos % 8 != 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst format not supported");
if (src->mode_info.red_field_pos % 8 != 0
|| src->mode_info.green_field_pos % 8 != 0
|| src->mode_info.blue_field_pos % 8 != 0
|| src->mode_info.reserved_field_pos % 8 != 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "src format not supported");
if (dst->mode_info.red_field_pos != src->mode_info.red_field_pos
|| dst->mode_info.red_mask_size != src->mode_info.red_mask_size
|| dst->mode_info.green_field_pos != src->mode_info.green_field_pos
|| dst->mode_info.green_mask_size != src->mode_info.green_mask_size
|| dst->mode_info.blue_field_pos != src->mode_info.blue_field_pos
|| dst->mode_info.blue_mask_size != src->mode_info.blue_mask_size
|| dst->mode_info.reserved_field_pos !=
src->mode_info.reserved_field_pos
|| dst->mode_info.reserved_mask_size !=
src->mode_info.reserved_mask_size)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst and src not compatible");
if (dst->mode_info.bytes_per_pixel != src->mode_info.bytes_per_pixel)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst and src not compatible");
if (dst->mode_info.width == 0 || dst->mode_info.height == 0
|| src->mode_info.width == 0 || src->mode_info.height == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "bitmap has a zero dimension");
grub_uint8_t *ddata = dst->data;
grub_uint8_t *sdata = src->data;
int dw = dst->mode_info.width;
int dh = dst->mode_info.height;
int sw = src->mode_info.width;
int sh = src->mode_info.height;
int dstride = dst->mode_info.pitch;
int sstride = src->mode_info.pitch;
/* bytes_per_pixel is the same for both src and dst. */
int bytes_per_pixel = dst->mode_info.bytes_per_pixel;
int dy;
for (dy = 0; dy < dh; dy++)
{
int dx;
for (dx = 0; dx < dw; dx++)
{
grub_uint8_t *dptr;
grub_uint8_t *sptr;
int sx;
int sy;
int comp;
/* Compute the source coordinate that the destination coordinate
maps to. Note: sx/sw = dx/dw => sx = sw*dx/dw. */
sx = sw * dx / dw;
sy = sh * dy / dh;
/* Get the address of the pixels in src and dst. */
dptr = ddata + dy * dstride + dx * bytes_per_pixel;
sptr = sdata + sy * sstride + sx * bytes_per_pixel;
/* Copy the pixel color value. */
for (comp = 0; comp < bytes_per_pixel; comp++)
dptr[comp] = sptr[comp];
}
}
return GRUB_ERR_NONE;
}
/* Bilinear interpolation image scaling algorithm.
Copy the bitmap SRC to the bitmap DST, scaling the bitmap to fit the
dimensions of DST. This function uses the bilinear interpolation algorithm
to interpolate the pixels.
Supports only direct color modes which have components separated
into bytes (e.g., RGBA 8:8:8:8 or BGR 8:8:8 true color).
But because of this simplifying assumption, the implementation is
greatly simplified. */
static grub_err_t
scale_bilinear (struct grub_video_bitmap *dst, struct grub_video_bitmap *src)
{
/* Verify the simplifying assumptions. */
if (dst == 0 || src == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "null bitmap in scale func");
if (dst->mode_info.red_field_pos % 8 != 0
|| dst->mode_info.green_field_pos % 8 != 0
|| dst->mode_info.blue_field_pos % 8 != 0
|| dst->mode_info.reserved_field_pos % 8 != 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst format not supported");
if (src->mode_info.red_field_pos % 8 != 0
|| src->mode_info.green_field_pos % 8 != 0
|| src->mode_info.blue_field_pos % 8 != 0
|| src->mode_info.reserved_field_pos % 8 != 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "src format not supported");
if (dst->mode_info.red_field_pos != src->mode_info.red_field_pos
|| dst->mode_info.red_mask_size != src->mode_info.red_mask_size
|| dst->mode_info.green_field_pos != src->mode_info.green_field_pos
|| dst->mode_info.green_mask_size != src->mode_info.green_mask_size
|| dst->mode_info.blue_field_pos != src->mode_info.blue_field_pos
|| dst->mode_info.blue_mask_size != src->mode_info.blue_mask_size
|| dst->mode_info.reserved_field_pos !=
src->mode_info.reserved_field_pos
|| dst->mode_info.reserved_mask_size !=
src->mode_info.reserved_mask_size)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst and src not compatible");
if (dst->mode_info.bytes_per_pixel != src->mode_info.bytes_per_pixel)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "dst and src not compatible");
if (dst->mode_info.width == 0 || dst->mode_info.height == 0
|| src->mode_info.width == 0 || src->mode_info.height == 0)
return grub_error (GRUB_ERR_BAD_ARGUMENT, "bitmap has a zero dimension");
grub_uint8_t *ddata = dst->data;
grub_uint8_t *sdata = src->data;
int dw = dst->mode_info.width;
int dh = dst->mode_info.height;
int sw = src->mode_info.width;
int sh = src->mode_info.height;
int dstride = dst->mode_info.pitch;
int sstride = src->mode_info.pitch;
/* bytes_per_pixel is the same for both src and dst. */
int bytes_per_pixel = dst->mode_info.bytes_per_pixel;
int dy;
for (dy = 0; dy < dh; dy++)
{
int dx;
for (dx = 0; dx < dw; dx++)
{
grub_uint8_t *dptr;
grub_uint8_t *sptr;
int sx;
int sy;
int comp;
/* Compute the source coordinate that the destination coordinate
maps to. Note: sx/sw = dx/dw => sx = sw*dx/dw. */
sx = sw * dx / dw;
sy = sh * dy / dh;
/* Get the address of the pixels in src and dst. */
dptr = ddata + dy * dstride + dx * bytes_per_pixel;
sptr = sdata + sy * sstride + sx * bytes_per_pixel;
/* If we have enough space to do so, use bilinear interpolation.
Otherwise, fall back to nearest neighbor for this pixel. */
if (sx < sw - 1 && sy < sh - 1)
{
/* Do bilinear interpolation. */
/* Fixed-point .8 numbers representing the fraction of the
distance in the x (u) and y (v) direction within the
box of 4 pixels in the source. */
int u = (256 * sw * dx / dw) - (sx * 256);
int v = (256 * sh * dy / dh) - (sy * 256);
for (comp = 0; comp < bytes_per_pixel; comp++)
{
/* Get the component's values for the
four source corner pixels. */
grub_uint8_t f00 = sptr[comp];
grub_uint8_t f10 = sptr[comp + bytes_per_pixel];
grub_uint8_t f01 = sptr[comp + sstride];
grub_uint8_t f11 = sptr[comp + sstride + bytes_per_pixel];
/* Do linear interpolations along the top and bottom
rows of the box. */
grub_uint8_t f0y = (256 - v) * f00 / 256 + v * f01 / 256;
grub_uint8_t f1y = (256 - v) * f10 / 256 + v * f11 / 256;
/* Interpolate vertically. */
grub_uint8_t fxy = (256 - u) * f0y / 256 + u * f1y / 256;
dptr[comp] = fxy;
}
}
else
{
/* Fall back to nearest neighbor interpolation. */
/* Copy the pixel color value. */
for (comp = 0; comp < bytes_per_pixel; comp++)
dptr[comp] = sptr[comp];
}
}
}
return GRUB_ERR_NONE;
}

View file

@ -93,7 +93,7 @@ grub_video_gop_get_bpp (struct grub_efi_gop_mode_info *in)
total_mask = in->pixel_bitmask.r | in->pixel_bitmask.g
| in->pixel_bitmask.b | in->pixel_bitmask.a;
for (i = 31; i >= 0; i--)
if (total_mask & (1 << i))
return i + 1;
@ -137,7 +137,7 @@ grub_video_gop_fill_mode_info (struct grub_efi_gop_mode_info *in,
out->bpp = grub_video_gop_get_bpp (in);
out->bytes_per_pixel = out->bpp >> 3;
if (!out->bpp)
return grub_error (GRUB_ERR_IO, "Unsupported video mode");
return grub_error (GRUB_ERR_IO, "unsupported video mode");
out->pitch = in->pixels_per_scanline * out->bytes_per_pixel;
switch (in->pixel_format)
@ -176,7 +176,7 @@ grub_video_gop_fill_mode_info (struct grub_efi_gop_mode_info *in,
break;
default:
return grub_error (GRUB_ERR_IO, "Unsupported video mode");
return grub_error (GRUB_ERR_IO, "unsupported video mode");
}
out->blit_format = grub_video_get_blit_format (out);
@ -185,7 +185,7 @@ grub_video_gop_fill_mode_info (struct grub_efi_gop_mode_info *in,
static grub_err_t
grub_video_gop_setup (unsigned int width, unsigned int height,
unsigned int mode_type)
unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused)))
{
unsigned int depth;
struct grub_efi_gop_mode_info *info = NULL;
@ -212,7 +212,7 @@ grub_video_gop_setup (unsigned int width, unsigned int height,
found = 1;
}
}
if (!found)
{
unsigned mode;
@ -221,7 +221,7 @@ grub_video_gop_setup (unsigned int width, unsigned int height,
{
grub_efi_uintn_t size;
grub_efi_status_t status;
status = efi_call_4 (gop->query_mode, gop, mode, &size, &info);
if (status)
{
@ -255,7 +255,7 @@ grub_video_gop_setup (unsigned int width, unsigned int height,
* ((unsigned long long) bpp))
{
best_volume = ((unsigned long long) info->width)
* ((unsigned long long) info->height)
* ((unsigned long long) info->height)
* ((unsigned long long) bpp);
best_mode = mode;
}
@ -266,7 +266,7 @@ grub_video_gop_setup (unsigned int width, unsigned int height,
if (!found)
{
grub_dprintf ("video", "GOP: no mode found\n");
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching mode found.");
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching mode found");
}
if (best_mode != gop->mode->mode)
@ -293,8 +293,8 @@ grub_video_gop_setup (unsigned int width, unsigned int height,
grub_dprintf ("video", "GOP: initialising FB @ %p %dx%dx%d\n",
framebuffer.ptr, framebuffer.mode_info.width,
framebuffer.mode_info.height, framebuffer.mode_info.bpp);
err = grub_video_fb_create_render_target_from_pointer
err = grub_video_fb_create_render_target_from_pointer
(&framebuffer.render_target, &framebuffer.mode_info, framebuffer.ptr);
if (err)
@ -302,15 +302,15 @@ grub_video_gop_setup (unsigned int width, unsigned int height,
grub_dprintf ("video", "GOP: Couldn't create FB target\n");
return err;
}
err = grub_video_fb_set_active_render_target (framebuffer.render_target);
if (err)
{
grub_dprintf ("video", "GOP: Couldn't set FB target\n");
return err;
}
err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
grub_video_fbstd_colors);
@ -318,7 +318,7 @@ grub_video_gop_setup (unsigned int width, unsigned int height,
grub_dprintf ("video", "GOP: Couldn't set palette\n");
else
grub_dprintf ("video", "GOP: Success\n");
return err;
}
@ -353,6 +353,7 @@ grub_video_gop_get_info_and_fini (struct grub_video_mode_info *mode_info,
static struct grub_video_adapter grub_video_gop_adapter =
{
.name = "EFI GOP driver",
.id = GRUB_VIDEO_DRIVER_EFI_GOP,
.init = grub_video_gop_init,
.fini = grub_video_gop_fini,

View file

@ -92,7 +92,7 @@ find_framebuf (grub_uint32_t *fb_base, grub_uint32_t *line_len)
{
grub_pci_address_t addr;
addr = grub_pci_make_address (dev, 2);
addr = grub_pci_make_address (dev, GRUB_PCI_REG_CLASS);
if (grub_pci_read (addr) >> 24 == 0x3)
{
int i;
@ -198,7 +198,7 @@ grub_video_uga_fini (void)
static grub_err_t
grub_video_uga_setup (unsigned int width, unsigned int height,
unsigned int mode_type)
unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused)))
{
unsigned int depth;
int found = 0;
@ -266,7 +266,7 @@ grub_video_uga_setup (unsigned int width, unsigned int height,
return err;
}
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching mode found.");
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching mode found");
}
static grub_err_t
@ -300,6 +300,7 @@ grub_video_uga_get_info_and_fini (struct grub_video_mode_info *mode_info,
static struct grub_video_adapter grub_video_uga_adapter =
{
.name = "EFI UGA driver",
.id = GRUB_VIDEO_DRIVER_EFI_UGA,
.init = grub_video_uga_init,
.fini = grub_video_uga_fini,

View file

@ -66,6 +66,8 @@ grub_video_fb_init (void)
grub_err_t
grub_video_fb_fini (void)
{
/* TODO: destroy render targets. */
grub_free (palette);
render_target = 0;
palette = 0;
@ -974,32 +976,83 @@ grub_video_fb_scroll (grub_video_color_t color, int dx, int dy)
{
/* 3. Move data in render target. */
struct grub_video_fbblit_info target;
grub_uint8_t *src;
grub_uint8_t *dst;
int j;
int i, j;
int linedelta, linelen;
target.mode_info = &render_target->mode_info;
target.data = render_target->data;
/* Check vertical direction of the move. */
if (dy <= 0)
/* 3a. Move data upwards. */
for (j = 0; j < height; j++)
{
dst = grub_video_fb_get_video_ptr (&target, dst_x, dst_y + j);
src = grub_video_fb_get_video_ptr (&target, src_x, src_y + j);
grub_memmove (dst, src,
width * target.mode_info->bytes_per_pixel);
}
linedelta = target.mode_info->pitch
- width * target.mode_info->bytes_per_pixel;
linelen = width * target.mode_info->bytes_per_pixel;
#define DO_SCROLL \
/* Check vertical direction of the move. */ \
if (dy < 0 || (dy == 0 && dx < 0)) \
{ \
dst = (void *) grub_video_fb_get_video_ptr (&target, \
dst_x, dst_y); \
src = (void *) grub_video_fb_get_video_ptr (&target, \
src_x, src_y); \
/* 3a. Move data upwards. */ \
for (j = 0; j < height; j++) \
{ \
for (i = 0; i < linelen; i++) \
*(dst++) = *(src++); \
dst += linedelta; \
src += linedelta; \
} \
} \
else \
{ \
/* 3b. Move data downwards. */ \
dst = (void *) grub_video_fb_get_video_ptr (&target, \
dst_x + width - 1, \
dst_y + height - 1); \
src = (void *) grub_video_fb_get_video_ptr (&target, \
src_x + width - 1, \
src_y + height - 1); \
for (j = 0; j < height; j++) \
{ \
for (i = 0; i < linelen; i++) \
*(dst--) = *(src--); \
dst -= linedelta; \
src -= linedelta; \
} \
}
/* If everything is aligned on 32-bit use 32-bit copy. */
if ((grub_addr_t) grub_video_fb_get_video_ptr (&target, src_x, src_y)
% sizeof (grub_uint32_t) == 0
&& (grub_addr_t) grub_video_fb_get_video_ptr (&target, dst_x, dst_y)
% sizeof (grub_uint32_t) == 0
&& linelen % sizeof (grub_uint32_t) == 0
&& linedelta % sizeof (grub_uint32_t) == 0)
{
grub_uint32_t *src, *dst;
linelen /= sizeof (grub_uint32_t);
linedelta /= sizeof (grub_uint32_t);
DO_SCROLL
}
/* If everything is aligned on 16-bit use 16-bit copy. */
else if ((grub_addr_t) grub_video_fb_get_video_ptr (&target, src_x, src_y)
% sizeof (grub_uint16_t) == 0
&& (grub_addr_t) grub_video_fb_get_video_ptr (&target,
dst_x, dst_y)
% sizeof (grub_uint16_t) == 0
&& linelen % sizeof (grub_uint16_t) == 0
&& linedelta % sizeof (grub_uint16_t) == 0)
{
grub_uint16_t *src, *dst;
linelen /= sizeof (grub_uint16_t);
linedelta /= sizeof (grub_uint16_t);
DO_SCROLL
}
/* If not aligned at all use 8-bit copy. */
else
/* 3b. Move data downwards. */
for (j = (height - 1); j >= 0; j--)
{
dst = grub_video_fb_get_video_ptr (&target, dst_x, dst_y + j);
src = grub_video_fb_get_video_ptr (&target, src_x, src_y + j);
grub_memmove (dst, src,
width * target.mode_info->bytes_per_pixel);
}
{
grub_uint8_t *src, *dst;
DO_SCROLL
}
}
/* 4. Fill empty space with specified color. In this implementation
@ -1048,7 +1101,7 @@ grub_video_fb_create_render_target (struct grub_video_fbrender_target **result,
|| (width == 0)
|| (height == 0))
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"invalid argument given.");
"invalid argument given");
/* Allocate memory for render target. */
target = grub_malloc (sizeof (struct grub_video_fbrender_target));
@ -1168,7 +1221,7 @@ grub_video_fb_set_active_render_target (struct grub_video_fbrender_target *targe
{
if (! target->data)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"invalid render target given.");
"invalid render target given");
render_target = target;
@ -1182,3 +1235,53 @@ grub_video_fb_get_active_render_target (struct grub_video_fbrender_target **targ
return GRUB_ERR_NONE;
}
static grub_err_t
doublebuf_blit_update_screen (struct grub_video_fbrender_target *front,
struct grub_video_fbrender_target *back)
{
grub_memcpy (front->data, back->data,
front->mode_info.pitch * front->mode_info.height);
return GRUB_ERR_NONE;
}
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)
{
grub_video_fb_delete_render_target (*front);
*front = 0;
return grub_errno;
}
err = grub_video_fb_create_render_target_from_pointer (back, &mode_info,
offscreen_buffer);
if (err)
{
grub_video_fb_delete_render_target (*front);
grub_free (offscreen_buffer);
*front = 0;
return grub_errno;
}
(*back)->is_allocated = 1;
*update_screen = doublebuf_blit_update_screen;
return GRUB_ERR_NONE;
}

View file

@ -39,13 +39,25 @@ static grub_uint32_t last_set_mode = 3;
static struct
{
struct grub_video_mode_info mode_info;
struct grub_video_render_target *render_target;
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;
@ -350,6 +362,7 @@ static grub_err_t
grub_video_vbe_fini (void)
{
grub_vbe_status_t status;
grub_err_t err;
/* Restore old video mode. */
status = grub_vbe_bios_set_mode (initial_vbe_mode, 0);
@ -362,14 +375,193 @@ grub_video_vbe_fini (void)
grub_free (vbe_mode_list);
vbe_mode_list = NULL;
/* TODO: destroy render targets. */
err = grub_video_fb_fini ();
grub_free (framebuffer.offscreen_buffer);
return err;
}
return grub_video_fb_fini ();
/*
Set framebuffer render target page and display the proper page, based on
`doublebuf_state.render_page' and `doublebuf_state.displayed_page',
respectively.
*/
static grub_err_t
doublebuf_pageflipping_commit (void)
{
/* Tell the video adapter to display the new front page. */
int display_start_line
= framebuffer.mode_info.height * framebuffer.displayed_page;
grub_vbe_status_t vbe_err =
grub_vbe_bios_set_display_start (0, display_start_line);
if (vbe_err != GRUB_VBE_STATUS_OK)
return grub_error (GRUB_ERR_IO, "couldn't commit pageflip");
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_type, unsigned int mode_mask)
{
grub_uint16_t *p;
struct grub_vbe_mode_info_block vbe_mode_info;
@ -415,32 +607,40 @@ grub_video_vbe_setup (unsigned int width, unsigned int height,
/* Not compatible memory model. */
continue;
if ((vbe_mode_info.x_resolution != width)
|| (vbe_mode_info.y_resolution != height))
if (((vbe_mode_info.x_resolution != width)
|| (vbe_mode_info.y_resolution != height)) && width != 0 && height != 0)
/* Non matching resolution. */
continue;
/* Check if user requested RGB or index color mode. */
if ((mode_type & GRUB_VIDEO_MODE_TYPE_COLOR_MASK) != 0)
if ((mode_mask & GRUB_VIDEO_MODE_TYPE_COLOR_MASK) != 0)
{
if (((mode_type & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR) != 0)
&& (vbe_mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL))
/* Requested only index color modes. */
continue;
unsigned my_mode_type = 0;
if (((mode_type & GRUB_VIDEO_MODE_TYPE_RGB) != 0)
&& (vbe_mode_info.memory_model != GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR))
/* Requested only RGB modes. */
continue;
if (vbe_mode_info.memory_model == GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL)
my_mode_type |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
if (vbe_mode_info.memory_model == GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR)
my_mode_type |= GRUB_VIDEO_MODE_TYPE_RGB;
if ((my_mode_type & mode_mask
& (GRUB_VIDEO_MODE_TYPE_RGB | GRUB_VIDEO_MODE_TYPE_INDEX_COLOR))
!= (mode_type & mode_mask
& (GRUB_VIDEO_MODE_TYPE_RGB
| GRUB_VIDEO_MODE_TYPE_INDEX_COLOR)))
continue;
}
/* If there is a request for specific depth, ignore others. */
if ((depth != 0) && (vbe_mode_info.bits_per_pixel != depth))
continue;
/* Select mode with most number of bits per pixel. */
/* Select mode with most of "volume" (size of framebuffer in bits). */
if (best_vbe_mode != 0)
if (vbe_mode_info.bits_per_pixel < best_vbe_mode_info.bits_per_pixel)
if ((grub_uint64_t) vbe_mode_info.bits_per_pixel
* vbe_mode_info.x_resolution * vbe_mode_info.y_resolution
< (grub_uint64_t) best_vbe_mode_info.bits_per_pixel
* best_vbe_mode_info.x_resolution * best_vbe_mode_info.y_resolution)
continue;
/* Save so far best mode information for later use. */
@ -483,12 +683,12 @@ grub_video_vbe_setup (unsigned int width, unsigned int height,
framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info);
err = grub_video_fb_create_render_target_from_pointer (&framebuffer.render_target, &framebuffer.mode_info, framebuffer.ptr);
/* Set up double buffering and targets. */
err = double_buffering_init (mode_type, mode_mask);
if (err)
return err;
err = grub_video_fb_set_active_render_target (framebuffer.render_target);
err = grub_video_fb_set_active_render_target (framebuffer.back_target);
if (err)
return err;
@ -500,7 +700,7 @@ grub_video_vbe_setup (unsigned int width, unsigned int height,
}
/* Couldn't found matching mode. */
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching mode found.");
return grub_error (GRUB_ERR_UNKNOWN_DEVICE, "no matching mode found");
}
static grub_err_t
@ -525,7 +725,15 @@ grub_video_vbe_set_palette (unsigned int start, unsigned int count,
static grub_err_t
grub_video_vbe_swap_buffers (void)
{
/* TODO: Implement buffer swapping. */
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;
}
@ -533,30 +741,46 @@ 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.render_target;
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;
*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;
}
static struct grub_video_adapter grub_video_vbe_adapter =
{
.name = "VESA BIOS Extension Video Driver",
.id = GRUB_VIDEO_DRIVER_VBE,
.init = grub_video_vbe_init,
.fini = grub_video_vbe_fini,
@ -579,7 +803,7 @@ static struct grub_video_adapter grub_video_vbe_adapter =
.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_fb_get_active_render_target,
.get_active_render_target = grub_video_vbe_get_active_render_target,
.next = 0
};

View file

@ -54,6 +54,10 @@ static const grub_uint8_t jpeg_zigzag_order[64] = {
53, 60, 61, 54, 47, 55, 62, 63
};
#ifdef JPEG_DEBUG
static grub_command_t cmd;
#endif
typedef int jpeg_data_unit_t[64];
struct grub_jpeg_data
@ -695,8 +699,8 @@ grub_video_reader_jpeg (struct grub_video_bitmap **bitmap,
#if defined(JPEG_DEBUG)
static grub_err_t
grub_cmd_jpegtest (struct grub_arg_list *state __attribute__ ((unused)),
int argc, char **args)
grub_cmd_jpegtest (grub_command_t cmd __attribute__ ((unused)),
int argc, char **args)
{
struct grub_video_bitmap *bitmap = 0;
@ -730,16 +734,16 @@ GRUB_MOD_INIT (jpeg)
grub_video_bitmap_reader_register (&jpg_reader);
grub_video_bitmap_reader_register (&jpeg_reader);
#if defined(JPEG_DEBUG)
grub_register_command ("jpegtest", grub_cmd_jpegtest,
GRUB_COMMAND_FLAG_BOTH, "jpegtest FILE",
"Tests loading of JPEG bitmap.", 0);
cmd = grub_register_command ("jpegtest", grub_cmd_jpegtest,
"FILE",
"Tests loading of JPEG bitmap.");
#endif
}
GRUB_MOD_FINI (jpeg)
{
#if defined(JPEG_DEBUG)
grub_unregister_command ("jpegtest");
grub_unregister_command (cmd);
#endif
grub_video_bitmap_reader_unregister (&jpeg_reader);
grub_video_bitmap_reader_unregister (&jpg_reader);

View file

@ -1,6 +1,6 @@
/*
* GRUB -- GRand Unified Bootloader
* Copyright (C) 2008 Free Software Foundation, Inc.
* Copyright (C) 2008,2009 Free Software Foundation, Inc.
*
* GRUB is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -73,6 +73,10 @@
#define DEFLATE_HUFF_LEN 16
#ifdef PNG_DEBUG
static grub_command_t cmd;
#endif
struct huff_table
{
int *values, *maxval, *offset;
@ -866,7 +870,7 @@ grub_video_reader_png (struct grub_video_bitmap **bitmap,
#if defined(PNG_DEBUG)
static grub_err_t
grub_cmd_pngtest (struct grub_arg_list *state __attribute__ ((unused)),
grub_cmd_pngtest (grub_command_t cmd __attribute__ ((unused)),
int argc, char **args)
{
struct grub_video_bitmap *bitmap = 0;
@ -894,16 +898,16 @@ GRUB_MOD_INIT (png)
{
grub_video_bitmap_reader_register (&png_reader);
#if defined(PNG_DEBUG)
grub_register_command ("pngtest", grub_cmd_pngtest,
GRUB_COMMAND_FLAG_BOTH, "pngtest FILE",
"Tests loading of PNG bitmap.", 0);
cmd = grub_register_command ("pngtest", grub_cmd_pngtest,
"FILE",
"Tests loading of PNG bitmap.");
#endif
}
GRUB_MOD_FINI (png)
{
#if defined(PNG_DEBUG)
grub_unregister_command ("pngtest");
grub_unregister_command (cmd);
#endif
grub_video_bitmap_reader_unregister (&png_reader);
}

View file

@ -29,6 +29,7 @@
#if defined(TGA_DEBUG)
#define dump_int_field(x) grub_printf( #x " = %d (0x%04x)\n", x, x);
static grub_command_t cmd;
#endif
enum
@ -370,7 +371,7 @@ grub_video_reader_tga (struct grub_video_bitmap **bitmap,
default:
grub_file_close (file);
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
"Unsupported bitmap format (unknown encoding).");
"unsupported bitmap format (unknown encoding)");
}
/* Check that bitmap depth is supported. */
@ -387,7 +388,7 @@ grub_video_reader_tga (struct grub_video_bitmap **bitmap,
default:
grub_file_close (file);
return grub_error (GRUB_ERR_BAD_FILE_TYPE,
"Unsupported bitmap format (bpp=%d).",
"unsupported bitmap format (bpp=%d)",
header.image_bpp);
}
@ -452,7 +453,7 @@ grub_video_reader_tga (struct grub_video_bitmap **bitmap,
#if defined(TGA_DEBUG)
static grub_err_t
grub_cmd_tgatest (struct grub_arg_list *state __attribute__ ((unused)),
grub_cmd_tgatest (grub_command_t cmd __attribute__ ((unused)),
int argc, char **args)
{
struct grub_video_bitmap *bitmap = 0;
@ -480,15 +481,15 @@ GRUB_MOD_INIT(tga)
{
grub_video_bitmap_reader_register (&tga_reader);
#if defined(TGA_DEBUG)
grub_register_command ("tgatest", grub_cmd_tgatest, GRUB_COMMAND_FLAG_BOTH,
"tgatest FILE", "Tests loading of TGA bitmap.", 0);
cmd = grub_register_command ("tgatest", grub_cmd_tgatest,
"FILE", "Tests loading of TGA bitmap.");
#endif
}
GRUB_MOD_FINI(tga)
{
#if defined(TGA_DEBUG)
grub_unregister_command ("tgatest");
grub_unregister_command (cmd);
#endif
grub_video_bitmap_reader_unregister (&tga_reader);
}

229
video/sm712.c Normal file
View file

@ -0,0 +1,229 @@
/*
* 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>
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;
} framebuffer;
static grub_err_t
grub_video_sm712_video_init (void)
{
/* Reset frame buffer. */
grub_memset (&framebuffer, 0, sizeof(framebuffer));
return grub_video_fb_init ();
}
static grub_err_t
grub_video_sm712_video_fini (void)
{
if (framebuffer.mapped)
grub_pci_device_unmap_range (framebuffer.dev, framebuffer.ptr,
1024 * 600 * 2);
return grub_video_fb_fini ();
}
static grub_err_t
grub_video_sm712_setup (unsigned int width, unsigned int height,
unsigned int mode_type, unsigned int mode_mask __attribute__ ((unused)))
{
int depth;
grub_err_t err;
int found = 0;
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 __attribute__ ((unused)))
{
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 != 0x0712126f)
return 0;
found = 1;
addr = grub_pci_make_address (dev, GRUB_PCI_REG_ADDRESS_REG0);
framebuffer.base = grub_pci_read (addr);
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 != 1024 && width != 0) || (height != 600 && height != 0)
|| (depth != 16 && depth != 0))
return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET,
"Only 1024x600x16 is supported");
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 */
}
/* Fill mode info details. */
framebuffer.mode_info.width = 1024;
framebuffer.mode_info.height = 600;
framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB;
framebuffer.mode_info.bpp = 16;
framebuffer.mode_info.bytes_per_pixel = 2;
framebuffer.mode_info.pitch = 1024 * 2;
framebuffer.mode_info.number_of_colors = 256;
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;
framebuffer.mode_info.reserved_mask_size = 0;
framebuffer.mode_info.reserved_field_pos = 0;
framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info);
/* We can safely discard volatile attribute. */
framebuffer.ptr = (void *) grub_pci_device_map_range (framebuffer.dev,
framebuffer.base,
1024 * 600 * 2);
framebuffer.mapped = 1;
err = grub_video_fb_create_render_target_from_pointer (&framebuffer.render_target, &framebuffer.mode_info, framebuffer.ptr);
if (err)
return err;
err = grub_video_fb_set_active_render_target (framebuffer.render_target);
if (err)
return err;
/* Copy default palette to initialize emulated palette. */
err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS,
grub_video_fbstd_colors);
return err;
}
static grub_err_t
grub_video_sm712_set_palette (unsigned int start, unsigned int count,
struct grub_video_palette_data *palette_data)
{
if (framebuffer.index_color_mode)
{
/* TODO: Implement setting indexed color mode palette to hardware. */
}
/* Then set color to emulated palette. */
return grub_video_fb_set_palette (start, count, palette_data);
}
static grub_err_t
grub_video_sm712_swap_buffers (void)
{
/* TODO: Implement buffer swapping. */
return GRUB_ERR_NONE;
}
static grub_err_t
grub_video_sm712_set_active_render_target (struct grub_video_render_target *target)
{
if (target == GRUB_VIDEO_RENDER_TARGET_DISPLAY)
target = framebuffer.render_target;
return grub_video_fb_set_active_render_target (target);
}
static grub_err_t
grub_video_sm712_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;
grub_video_fb_fini ();
return GRUB_ERR_NONE;
}
static struct grub_video_adapter grub_video_sm712_adapter =
{
.name = "SM712 Video Driver",
.init = grub_video_sm712_video_init,
.fini = grub_video_sm712_video_fini,
.setup = grub_video_sm712_setup,
.get_info = grub_video_fb_get_info,
.get_info_and_fini = grub_video_sm712_get_info_and_fini,
.set_palette = grub_video_sm712_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_sm712_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_sm712_set_active_render_target,
.get_active_render_target = grub_video_fb_get_active_render_target,
.next = 0
};
GRUB_MOD_INIT(video_sm712)
{
grub_video_register (&grub_video_sm712_adapter);
}
GRUB_MOD_FINI(video_sm712)
{
grub_video_unregister (&grub_video_sm712_adapter);
}

View file

@ -81,7 +81,7 @@ grub_err_t
grub_video_get_info (struct grub_video_mode_info *mode_info)
{
if (! grub_video_adapter_active)
return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
/* If mode_info is NULL just report that video adapter is active. */
if (! mode_info)
@ -93,6 +93,14 @@ grub_video_get_info (struct grub_video_mode_info *mode_info)
return grub_video_adapter_active->get_info (mode_info);
}
grub_video_driver_id_t
grub_video_get_driver_id (void)
{
if (! grub_video_adapter_active)
return GRUB_VIDEO_DRIVER_NONE;
return grub_video_adapter_active->id;
}
/* Get information about active video mode. */
grub_err_t
grub_video_get_info_and_fini (struct grub_video_mode_info *mode_info,
@ -101,7 +109,7 @@ grub_video_get_info_and_fini (struct grub_video_mode_info *mode_info,
grub_err_t err;
if (! grub_video_adapter_active)
return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
err = grub_video_adapter_active->get_info_and_fini (mode_info, framebuffer);
if (err)
@ -209,7 +217,7 @@ grub_video_set_palette (unsigned int start, unsigned int count,
struct grub_video_palette_data *palette_data)
{
if (! grub_video_adapter_active)
return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
return grub_video_adapter_active->set_palette (start, count, palette_data);
}
@ -220,7 +228,7 @@ grub_video_get_palette (unsigned int start, unsigned int count,
struct grub_video_palette_data *palette_data)
{
if (! grub_video_adapter_active)
return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
return grub_video_adapter_active->get_palette (start, count, palette_data);
}
@ -231,7 +239,7 @@ grub_video_set_viewport (unsigned int x, unsigned int y,
unsigned int width, unsigned int height)
{
if (! grub_video_adapter_active)
return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
return grub_video_adapter_active->set_viewport (x, y, width, height);
}
@ -242,7 +250,7 @@ grub_video_get_viewport (unsigned int *x, unsigned int *y,
unsigned int *width, unsigned int *height)
{
if (! grub_video_adapter_active)
return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
return grub_video_adapter_active->get_viewport (x, y, width, height);
}
@ -285,7 +293,7 @@ grub_video_unmap_color (grub_video_color_t color, grub_uint8_t *red,
grub_uint8_t *alpha)
{
if (! grub_video_adapter_active)
return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
return grub_video_adapter_active->unmap_color (color,
red,
@ -300,7 +308,7 @@ grub_video_fill_rect (grub_video_color_t color, int x, int y,
unsigned int width, unsigned int height)
{
if (! grub_video_adapter_active)
return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
return grub_video_adapter_active->fill_rect (color, x, y, width, height);
}
@ -313,7 +321,7 @@ grub_video_blit_bitmap (struct grub_video_bitmap *bitmap,
unsigned int width, unsigned int height)
{
if (! grub_video_adapter_active)
return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
return grub_video_adapter_active->blit_bitmap (bitmap, oper, x, y,
offset_x, offset_y,
@ -328,7 +336,7 @@ grub_video_blit_render_target (struct grub_video_render_target *target,
unsigned int width, unsigned int height)
{
if (! grub_video_adapter_active)
return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
return grub_video_adapter_active->blit_render_target (target, oper, x, y,
offset_x, offset_y,
@ -340,7 +348,7 @@ grub_err_t
grub_video_scroll (grub_video_color_t color, int dx, int dy)
{
if (! grub_video_adapter_active)
return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
return grub_video_adapter_active->scroll (color, dx, dy);
}
@ -350,7 +358,7 @@ grub_err_t
grub_video_swap_buffers (void)
{
if (! grub_video_adapter_active)
return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
return grub_video_adapter_active->swap_buffers ();
}
@ -362,7 +370,7 @@ grub_video_create_render_target (struct grub_video_render_target **result,
unsigned int mode_type)
{
if (! grub_video_adapter_active)
return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
return grub_video_adapter_active->create_render_target (result,
width, height,
@ -374,7 +382,7 @@ grub_err_t
grub_video_delete_render_target (struct grub_video_render_target *target)
{
if (! grub_video_adapter_active)
return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
return grub_video_adapter_active->delete_render_target (target);
}
@ -384,7 +392,7 @@ grub_err_t
grub_video_set_active_render_target (struct grub_video_render_target *target)
{
if (! grub_video_adapter_active)
return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
return grub_video_adapter_active->set_active_render_target (target);
}
@ -394,26 +402,86 @@ grub_err_t
grub_video_get_active_render_target (struct grub_video_render_target **target)
{
if (! grub_video_adapter_active)
return grub_error (GRUB_ERR_BAD_DEVICE, "No video mode activated");
return grub_error (GRUB_ERR_BAD_DEVICE, "no video mode activated");
return grub_video_adapter_active->get_active_render_target (target);
}
/* Parse <width>x<height>[x<depth>]*/
static grub_err_t
parse_modespec (const char *current_mode, int *width, int *height, int *depth)
{
const char *value;
const char *param = current_mode;
*width = *height = *depth = -1;
if (grub_strcmp (param, "auto") == 0)
{
*width = *height = 0;
return GRUB_ERR_NONE;
}
/* Find width value. */
value = param;
param = grub_strchr(param, 'x');
if (param == NULL)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"Invalid mode: %s\n",
current_mode);
param++;
*width = grub_strtoul (value, 0, 0);
if (grub_errno != GRUB_ERR_NONE)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"Invalid mode: %s\n",
current_mode);
/* Find height value. */
value = param;
param = grub_strchr(param, 'x');
if (param == NULL)
{
*height = grub_strtoul (value, 0, 0);
if (grub_errno != GRUB_ERR_NONE)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"Invalid mode: %s\n",
current_mode);
}
else
{
/* We have optional color depth value. */
param++;
*height = grub_strtoul (value, 0, 0);
if (grub_errno != GRUB_ERR_NONE)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"Invalid mode: %s\n",
current_mode);
/* Convert color depth value. */
value = param;
*depth = grub_strtoul (value, 0, 0);
if (grub_errno != GRUB_ERR_NONE)
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"Invalid mode: %s\n",
current_mode);
}
return GRUB_ERR_NONE;
}
grub_err_t
grub_video_set_mode (const char *modestring,
int NESTED_FUNC_ATTR (*hook) (grub_video_adapter_t p,
struct grub_video_mode_info *mode_info))
unsigned int modemask,
unsigned int modevalue)
{
char *tmp;
char *next_mode;
char *current_mode;
char *param;
char *value;
char *modevar;
int width = -1;
int height = -1;
int depth = -1;
int flags = 0;
modevalue &= modemask;
/* Take copy of env.var. as we don't want to modify that. */
modevar = grub_strdup (modestring);
@ -429,26 +497,26 @@ grub_video_set_mode (const char *modestring,
|| grub_memcmp (next_mode, "keep,", sizeof ("keep,") - 1) == 0
|| grub_memcmp (next_mode, "keep;", sizeof ("keep;") - 1) == 0)
{
struct grub_video_mode_info mode_info;
int suitable = 1;
grub_err_t err;
grub_memset (&mode_info, 0, sizeof (mode_info));
if (grub_video_adapter_active)
{
struct grub_video_mode_info mode_info;
grub_memset (&mode_info, 0, sizeof (mode_info));
err = grub_video_get_info (&mode_info);
if (err)
{
suitable = 0;
grub_errno = GRUB_ERR_NONE;
}
if ((mode_info.mode_type & modemask) != modevalue)
suitable = 0;
}
else
mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_PURE_TEXT;
else if (((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modemask) != 0)
&& ((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modevalue) == 0))
suitable = 0;
if (suitable && hook)
suitable = hook (grub_video_adapter_active, &mode_info);
if (suitable)
{
grub_free (modevar);
@ -460,7 +528,7 @@ grub_video_set_mode (const char *modestring,
grub_free (modevar);
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"No suitable mode found.");
"no suitable mode found");
}
/* Skip separator. */
@ -482,15 +550,16 @@ grub_video_set_mode (const char *modestring,
/* Loop until all modes has been tested out. */
while (next_mode != NULL)
{
int width = -1;
int height = -1;
int depth = -1;
grub_err_t err;
unsigned int flags = modevalue;
unsigned int flagmask = modemask;
/* Use last next_mode as current mode. */
tmp = next_mode;
/* Reset video mode settings. */
width = -1;
height = -1;
depth = -1;
flags = 0;
/* Save position of next mode and separate modes. */
for (; *next_mode; next_mode++)
if (*next_mode == ',' || *next_mode == ';')
@ -509,19 +578,16 @@ grub_video_set_mode (const char *modestring,
/* Initialize token holders. */
current_mode = tmp;
param = tmp;
value = NULL;
/* XXX: we assume that we're in pure text mode if
no video mode is initialized. Is it always true? */
if (grub_strcmp (param, "text") == 0)
if (grub_strcmp (current_mode, "text") == 0)
{
struct grub_video_mode_info mode_info;
grub_memset (&mode_info, 0, sizeof (mode_info));
mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_PURE_TEXT;
if (! hook || hook (0, &mode_info))
if (((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modemask) == 0)
|| ((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modevalue) != 0))
{
/* Valid mode found from adapter, and it has been activated.
Specify it as active adapter. */
@ -534,121 +600,31 @@ grub_video_set_mode (const char *modestring,
}
}
/* Parse <width>x<height>[x<depth>]*/
/* Find width value. */
value = param;
param = grub_strchr(param, 'x');
if (param == NULL)
err = parse_modespec (current_mode, &width, &height, &depth);
if (err)
{
grub_err_t rc;
/* First setup error message. */
rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
"Invalid mode: %s\n",
current_mode);
/* Free memory before returning. */
grub_free (modevar);
return rc;
}
*param = 0;
param++;
width = grub_strtoul (value, 0, 0);
if (grub_errno != GRUB_ERR_NONE)
{
grub_err_t rc;
/* First setup error message. */
rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
"Invalid mode: %s\n",
current_mode);
/* Free memory before returning. */
grub_free (modevar);
return rc;
}
/* Find height value. */
value = param;
param = grub_strchr(param, 'x');
if (param == NULL)
{
height = grub_strtoul (value, 0, 0);
if (grub_errno != GRUB_ERR_NONE)
{
grub_err_t rc;
/* First setup error message. */
rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
"Invalid mode: %s\n",
current_mode);
/* Free memory before returning. */
grub_free (modevar);
return rc;
}
}
else
{
/* We have optional color depth value. */
*param = 0;
param++;
height = grub_strtoul (value, 0, 0);
if (grub_errno != GRUB_ERR_NONE)
{
grub_err_t rc;
/* First setup error message. */
rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
"Invalid mode: %s\n",
current_mode);
/* Free memory before returning. */
grub_free (modevar);
return rc;
}
/* Convert color depth value. */
value = param;
depth = grub_strtoul (value, 0, 0);
if (grub_errno != GRUB_ERR_NONE)
{
grub_err_t rc;
/* First setup error message. */
rc = grub_error (GRUB_ERR_BAD_ARGUMENT,
"Invalid mode: %s\n",
current_mode);
/* Free memory before returning. */
grub_free (modevar);
return rc;
}
return err;
}
/* Try out video mode. */
/* If we have 8 or less bits, then assume that it is indexed color mode. */
if ((depth <= 8) && (depth != -1))
flags |= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR;
/* If user requested specific depth check if this depth is supported. */
if (depth != -1 && (flagmask & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
&&
(((flags & GRUB_VIDEO_MODE_TYPE_DEPTH_MASK)
!= ((depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
& GRUB_VIDEO_MODE_TYPE_DEPTH_MASK))))
continue;
/* We have more than 8 bits, then assume that it is RGB color mode. */
if (depth > 8)
flags |= GRUB_VIDEO_MODE_TYPE_RGB;
/* If user requested specific depth, forward that information to driver. */
if (depth != -1)
flags |= (depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
& GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
{
flags |= (depth << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
& GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
flagmask |= GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
}
/* Try to initialize requested mode. Ignore any errors. */
grub_video_adapter_t p;
@ -656,7 +632,6 @@ grub_video_set_mode (const char *modestring,
/* Loop thru all possible video adapter trying to find requested mode. */
for (p = grub_video_adapter_list; p; p = p->next)
{
grub_err_t err;
struct grub_video_mode_info mode_info;
grub_memset (&mode_info, 0, sizeof (mode_info));
@ -670,7 +645,7 @@ grub_video_set_mode (const char *modestring,
}
/* Try to initialize video mode. */
err = p->setup (width, height, flags);
err = p->setup (width, height, flags, flagmask);
if (err != GRUB_ERR_NONE)
{
p->fini ();
@ -686,7 +661,15 @@ grub_video_set_mode (const char *modestring,
continue;
}
if (hook && ! hook (p, &mode_info))
flags = mode_info.mode_type & ~GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
flags |= (mode_info.bpp << GRUB_VIDEO_MODE_TYPE_DEPTH_POS)
& GRUB_VIDEO_MODE_TYPE_DEPTH_MASK;
/* Check that mode is suitable for upper layer. */
if ((flags & GRUB_VIDEO_MODE_TYPE_PURE_TEXT)
? (((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modemask) != 0)
&& ((GRUB_VIDEO_MODE_TYPE_PURE_TEXT & modevalue) == 0))
: ((flags & modemask) != modevalue))
{
p->fini ();
grub_errno = GRUB_ERR_NONE;
@ -709,7 +692,7 @@ grub_video_set_mode (const char *modestring,
grub_free (modevar);
return grub_error (GRUB_ERR_BAD_ARGUMENT,
"No suitable mode found.");
"no suitable mode found");
}
/* Initialize Video API module. */