📄 vbe.c
字号:
if (y < 0) { height += y; offset_y -= y; y = 0; } /* 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 ((offset_x + width) > bitmap->mode_info.width) width = bitmap->mode_info.width - offset_x; if ((offset_y + height) > bitmap->mode_info.height) height = bitmap->mode_info.height - offset_y; /* Limit drawing to source render target dimensions. */ if (width > bitmap->mode_info.width) width = bitmap->mode_info.width; if (height > bitmap->mode_info.height) height = bitmap->mode_info.height; /* Add viewport offset. */ x += render_target->viewport.x; y += render_target->viewport.y; /* Use vbeblit_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; /* Do actual blitting. */ common_blitter (&target, &source, oper, x, y, width, height, offset_x, offset_y); return GRUB_ERR_NONE;}static grub_err_tgrub_video_vbe_blit_render_target (struct grub_video_render_target *source, enum grub_video_blit_operators oper, int x, int y, int offset_x, int offset_y, unsigned int width, unsigned int height){ struct grub_video_i386_vbeblit_info source_info; struct grub_video_i386_vbeblit_info target_info; /* Make sure there is something to do. */ if ((width == 0) || (height == 0)) return GRUB_ERR_NONE; if ((x >= (int)render_target->viewport.width) || (x + (int)width < 0)) return GRUB_ERR_NONE; if ((y >= (int)render_target->viewport.height) || (y + (int)height < 0)) return GRUB_ERR_NONE; if ((x + (int)source->mode_info.width) < 0) return GRUB_ERR_NONE; if ((y + (int)source->mode_info.height) < 0) return GRUB_ERR_NONE; if ((offset_x >= (int)source->mode_info.width) || (offset_x + (int)width < 0)) return GRUB_ERR_NONE; if ((offset_y >= (int)source->mode_info.height) || (offset_y + (int)height < 0)) return GRUB_ERR_NONE; /* If we have negative coordinates, optimize drawing to minimum. */ if (offset_x < 0) { width += offset_x; x -= offset_x; offset_x = 0; } if (offset_y < 0) { height += offset_y; y -= offset_y; offset_y = 0; } if (x < 0) { width += x; offset_x -= x; x = 0; } if (y < 0) { height += y; offset_y -= y; y = 0; } /* 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 ((offset_x + width) > source->mode_info.width) width = source->mode_info.width - offset_x; if ((offset_y + height) > source->mode_info.height) height = source->mode_info.height - offset_y; /* Limit drawing to source render target dimensions. */ if (width > source->mode_info.width) width = source->mode_info.width; if (height > source->mode_info.height) height = source->mode_info.height; /* Add viewport offset. */ x += render_target->viewport.x; y += render_target->viewport.y; /* Use vbeblit_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; /* Do actual blitting. */ common_blitter (&target_info, &source_info, oper, x, y, width, height, offset_x, offset_y); return GRUB_ERR_NONE;}static grub_err_tgrub_video_vbe_scroll (grub_video_color_t color, int dx, int dy){ int width; int height; int src_x; int src_y; int dst_x; int dst_y; /* 1. Check if we have something to do. */ 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); if (dx < 0) { src_x = render_target->viewport.x - dx; dst_x = render_target->viewport.x; } else { src_x = render_target->viewport.x; dst_x = render_target->viewport.x + dx; } if (dy < 0) { src_y = render_target->viewport.y - dy; dst_y = render_target->viewport.y; } else { src_y = render_target->viewport.y; dst_y = 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)) { /* 3. Move data in render target. */ struct grub_video_i386_vbeblit_info target; grub_uint8_t *src; grub_uint8_t *dst; int j; target.mode_info = &render_target->mode_info; target.data = render_target->data; for (j = 0; j < height; j++) { dst = grub_video_vbe_get_video_ptr (&target, dst_x, dst_y + j); src = grub_video_vbe_get_video_ptr (&target, src_x, src_y + j); grub_memmove (dst, src, width * target.mode_info->bytes_per_pixel); } } /* 4. Fill empty space with specified color. In this implementation there might be colliding areas but at the moment there is no need to optimize this. */ /* 4a. Fill top & bottom parts. */ if (dy > 0) grub_video_vbe_fill_rect (color, 0, 0, render_target->viewport.width, dy); else if (dy < 0) { if (render_target->viewport.height < grub_abs (dy)) dy = -render_target->viewport.height; grub_video_vbe_fill_rect (color, 0, render_target->viewport.height + dy, render_target->viewport.width, -dy); } /* 4b. Fill left & right parts. */ if (dx > 0) grub_video_vbe_fill_rect (color, 0, 0, dx, render_target->viewport.height); else if (dx < 0) { if (render_target->viewport.width < grub_abs (dx)) dx = -render_target->viewport.width; grub_video_vbe_fill_rect (color, render_target->viewport.width + dx, 0, -dx, render_target->viewport.height); } return GRUB_ERR_NONE;}static grub_err_t grub_video_vbe_swap_buffers (void){ /* TODO: Implement buffer swapping. */ return GRUB_ERR_NONE;}static grub_err_tgrub_video_vbe_create_render_target (struct grub_video_render_target **result, unsigned int width, unsigned int height, unsigned int mode_type){ struct grub_video_render_target *target; unsigned int size; /* Validate arguments. */ if ((! result) || (width == 0) || (height == 0)) return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid argument given."); /* Allocate memory for render target. */ target = grub_malloc (sizeof (struct grub_video_render_target)); if (! target) return grub_errno; /* TODO: Implement other types too. Currently only 32bit render targets are supported. */ /* Mark render target as allocated. */ target->is_allocated = 1; /* Maximize viewport. */ target->viewport.x = 0; target->viewport.y = 0; target->viewport.width = width; target->viewport.height = height; /* Setup render target format. */ target->mode_info.width = width; target->mode_info.height = height; target->mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB | GRUB_VIDEO_MODE_TYPE_ALPHA; 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 = 256; /* Emulated paletted. */ target->mode_info.red_mask_size = 8; target->mode_info.red_field_pos = 0; target->mode_info.green_mask_size = 8; target->mode_info.green_field_pos = 8; target->mode_info.blue_mask_size = 8; target->mode_info.blue_field_pos = 16; target->mode_info.reserved_mask_size = 8; target->mode_info.reserved_field_pos = 24; target->mode_info.blit_format = grub_video_get_blit_format (&target->mode_info); /* Calculate size needed for the data. */ size = (width * target->mode_info.bytes_per_pixel) * height; target->data = grub_malloc (size); if (! target->data) { grub_free (target); return grub_errno; } /* Clear render target with black and maximum transparency. */ grub_memset (target->data, 0, size); /* TODO: Add render target to render target list. */ /* Save result to caller. */ *result = target; return GRUB_ERR_NONE;}static grub_err_tgrub_video_vbe_delete_render_target (struct grub_video_render_target *target){ /* If there is no target, then just return without error. */ if (! target) return GRUB_ERR_NONE; /* TODO: Delist render target fron render target list. */ /* If this is software render target, free it's memory. */ if (target->is_allocated) grub_free (target->data); /* Free render target. */ grub_free (target); return GRUB_ERR_NONE;}static grub_err_tgrub_video_vbe_set_active_render_target (struct grub_video_render_target *target){ if (target == GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER) { render_target = &framebuffer.render_target; return GRUB_ERR_NONE; } if (target == GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER) return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET, "double buffering not implemented yet."); if (! target->data) return grub_error (GRUB_ERR_BAD_ARGUMENT, "invalid render target given."); render_target = target; return GRUB_ERR_NONE;}static struct grub_video_adapter grub_video_vbe_adapter = { .name = "VESA BIOS Extension Video Driver", .init = grub_video_vbe_init, .fini = grub_video_vbe_fini, .setup = grub_video_vbe_setup, .get_info = grub_video_vbe_get_info, .set_palette = grub_video_vbe_set_palette, .get_palette = grub_video_vbe_get_palette, .set_viewport = grub_video_vbe_set_viewport, .get_viewport = grub_video_vbe_get_viewport, .map_color = grub_video_vbe_map_color, .map_rgb = grub_video_vbe_map_rgb, .map_rgba = grub_video_vbe_map_rgba, .fill_rect = grub_video_vbe_fill_rect, .blit_glyph = grub_video_vbe_blit_glyph, .blit_bitmap = grub_video_vbe_blit_bitmap, .blit_render_target = grub_video_vbe_blit_render_target, .scroll = grub_video_vbe_scroll, .swap_buffers = grub_video_vbe_swap_buffers, .create_render_target = grub_video_vbe_create_render_target, .delete_render_target = grub_video_vbe_delete_render_target, .set_active_render_target = grub_video_vbe_set_active_render_target, .next = 0 };GRUB_MOD_INIT(video_i386_pc_vbe){ grub_video_register (&grub_video_vbe_adapter);}GRUB_MOD_FINI(video_i386_pc_vbe){ grub_video_unregister (&grub_video_vbe_adapter);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -