diff --git a/include/grub/fbfill.h b/include/grub/fbfill.h index 11e22c6..08cd7b8 100644 --- a/include/grub/fbfill.h +++ b/include/grub/fbfill.h @@ -24,6 +24,29 @@ struct grub_video_fbblit_info; +struct grub_video_fbrender_target +{ + /* Copy of the screen's mode info structure, except that width, height and + mode_type has been re-adjusted to requested render target settings. */ + struct grub_video_mode_info mode_info; + + struct + { + unsigned int x; + unsigned int y; + unsigned int width; + unsigned int height; + } viewport; + + /* Indicates whether the data has been allocated by us and must be freed + when render target is destroyed. */ + int is_allocated; + + /* Pointer to data. Can either be in video card memory or in local host's + memory. */ + void *data; +}; + void grub_video_fbfill (struct grub_video_fbblit_info *dst, grub_video_color_t color, int x, int y, diff --git a/include/grub/video_fb.h b/include/grub/video_fb.h index 9ae4101..03ef385 100644 --- a/include/grub/video_fb.h +++ b/include/grub/video_fb.h @@ -28,28 +28,7 @@ struct grub_video_fbblit_info; -struct grub_video_fbrender_target -{ - /* Copy of the screen's mode info structure, except that width, height and - mode_type has been re-adjusted to requested render target settings. */ - struct grub_video_mode_info mode_info; - - struct - { - unsigned int x; - unsigned int y; - unsigned int width; - unsigned int height; - } viewport; - - /* Indicates whether the data has been allocated by us and must be freed - when render target is destroyed. */ - int is_allocated; - - /* Pointer to data. Can either be in video card memory or in local host's - memory. */ - void *data; -}; +struct grub_video_fbrender_target; #define GRUB_VIDEO_FBSTD_NUMCOLORS 16 extern struct grub_video_palette_data grub_video_fbstd_colors[GRUB_VIDEO_FBSTD_NUMCOLORS]; @@ -126,6 +105,11 @@ grub_video_fb_create_render_target (struct grub_video_fbrender_target **result, unsigned int mode_type __attribute__ ((unused))); grub_err_t +grub_video_fb_create_render_target_from_pointer (struct grub_video_fbrender_target **result, + const struct grub_video_mode_info *mode_info, + void *ptr); + +grub_err_t grub_video_fb_delete_render_target (struct grub_video_fbrender_target *target); grub_err_t diff --git a/video/fb/video_fb.c b/video/fb/video_fb.c index f97d7ac..e4f8f6d 100644 --- a/video/fb/video_fb.c +++ b/video/fb/video_fb.c @@ -1081,6 +1081,45 @@ grub_video_fb_create_render_target (struct grub_video_fbrender_target **result, } grub_err_t +grub_video_fb_create_render_target_from_pointer (struct grub_video_fbrender_target **result, + const struct grub_video_mode_info *mode_info, + void *ptr) +{ + struct grub_video_fbrender_target *target; + unsigned y; + + /* Allocate memory for render target. */ + target = grub_malloc (sizeof (struct grub_video_fbrender_target)); + if (! target) + return grub_errno; + + /* Mark render target as unallocated. */ + target->is_allocated = 0; + target->data = ptr; + + grub_memcpy (&(target->mode_info), mode_info, sizeof (target->mode_info)); + + /* Reset viewport to match new mode. */ + target->viewport.x = 0; + target->viewport.y = 0; + target->viewport.width = mode_info->width; + target->viewport.height = mode_info->height; + + /* Mark framebuffer memory as non allocated. */ + target->is_allocated = 0; + + /* Clear render target with black and maximum transparency. */ + for (y = 0; y < mode_info->height; y++) + grub_memset (target->data + mode_info->pitch * y, 0, + mode_info->bytes_per_pixel * mode_info->width); + + /* Save result to caller. */ + *result = target; + + return GRUB_ERR_NONE; +} + +grub_err_t grub_video_fb_delete_render_target (struct grub_video_fbrender_target *target) { /* If there is no target, then just return without error. */ diff --git a/video/i386/pc/vbe.c b/video/i386/pc/vbe.c index f73242f..1a0f587 100644 --- a/video/i386/pc/vbe.c +++ b/video/i386/pc/vbe.c @@ -35,7 +35,8 @@ static struct grub_vbe_mode_info_block active_mode_info; static struct { - struct grub_video_render_target render_target; + 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; @@ -475,39 +476,29 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, in order to fasten later operations. */ mode_in_use = best_mode; - /* Fill mode info details in framebuffer's render target. */ - framebuffer.render_target.data = framebuffer.ptr; - framebuffer.render_target.mode_info.width = active_mode_info.x_resolution; - framebuffer.render_target.mode_info.height = active_mode_info.y_resolution; + /* Fill mode info details. */ + framebuffer.mode_info.width = active_mode_info.x_resolution; + framebuffer.mode_info.height = active_mode_info.y_resolution; if (framebuffer.index_color_mode) - framebuffer.render_target.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; + framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_INDEX_COLOR; else - framebuffer.render_target.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB; - - framebuffer.render_target.mode_info.bpp = active_mode_info.bits_per_pixel; - framebuffer.render_target.mode_info.bytes_per_pixel = framebuffer.bytes_per_pixel; - framebuffer.render_target.mode_info.pitch = framebuffer.bytes_per_scan_line; - framebuffer.render_target.mode_info.number_of_colors = 256; /* TODO: fix me. */ - framebuffer.render_target.mode_info.red_mask_size = active_mode_info.red_mask_size; - framebuffer.render_target.mode_info.red_field_pos = active_mode_info.red_field_position; - framebuffer.render_target.mode_info.green_mask_size = active_mode_info.green_mask_size; - framebuffer.render_target.mode_info.green_field_pos = active_mode_info.green_field_position; - framebuffer.render_target.mode_info.blue_mask_size = active_mode_info.blue_mask_size; - framebuffer.render_target.mode_info.blue_field_pos = active_mode_info.blue_field_position; - framebuffer.render_target.mode_info.reserved_mask_size = active_mode_info.rsvd_mask_size; - framebuffer.render_target.mode_info.reserved_field_pos = active_mode_info.rsvd_field_position; - - framebuffer.render_target.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.render_target.mode_info); - - /* Reset viewport to match new mode. */ - framebuffer.render_target.viewport.x = 0; - framebuffer.render_target.viewport.y = 0; - framebuffer.render_target.viewport.width = active_mode_info.x_resolution; - framebuffer.render_target.viewport.height = active_mode_info.y_resolution; - - /* Mark framebuffer memory as non allocated. */ - framebuffer.render_target.is_allocated = 0; + framebuffer.mode_info.mode_type = GRUB_VIDEO_MODE_TYPE_RGB; + + framebuffer.mode_info.bpp = active_mode_info.bits_per_pixel; + framebuffer.mode_info.bytes_per_pixel = framebuffer.bytes_per_pixel; + framebuffer.mode_info.pitch = framebuffer.bytes_per_scan_line; + framebuffer.mode_info.number_of_colors = 256; /* TODO: fix me. */ + framebuffer.mode_info.red_mask_size = active_mode_info.red_mask_size; + framebuffer.mode_info.red_field_pos = active_mode_info.red_field_position; + framebuffer.mode_info.green_mask_size = active_mode_info.green_mask_size; + framebuffer.mode_info.green_field_pos = active_mode_info.green_field_position; + framebuffer.mode_info.blue_mask_size = active_mode_info.blue_mask_size; + framebuffer.mode_info.blue_field_pos = active_mode_info.blue_field_position; + framebuffer.mode_info.reserved_mask_size = active_mode_info.rsvd_mask_size; + framebuffer.mode_info.reserved_field_pos = active_mode_info.rsvd_field_position; + + framebuffer.mode_info.blit_format = grub_video_get_blit_format (&framebuffer.mode_info); /* Copy default palette to initialize emulated palette. */ err = grub_video_fb_set_palette (0, GRUB_VIDEO_FBSTD_NUMCOLORS, @@ -515,8 +506,12 @@ grub_video_vbe_setup (unsigned int width, unsigned int height, if (err) return err; - /* Reset render target to framebuffer one. */ - return grub_video_fb_set_active_render_target (&framebuffer.render_target); + err = grub_video_fb_create_render_target_from_pointer (&framebuffer.render_target, &framebuffer.mode_info, framebuffer.ptr); + + if (err) + return err; + + return grub_video_fb_set_active_render_target (framebuffer.render_target); } /* Couldn't found matching mode. */ @@ -553,7 +548,7 @@ 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.render_target; return grub_video_fb_set_active_render_target (target); } @@ -562,12 +557,14 @@ static grub_err_t grub_video_vbe_get_info_and_fini (struct grub_video_mode_info *mode_info, void **framebuf) { - grub_err_t err; - err = grub_video_fb_get_info (mode_info); - if (err) - return err; + grub_memcpy (mode_info, &(framebuffer.mode_info), sizeof (*mode_info)); *framebuf = (char *) framebuffer.ptr; + grub_free (mode_list); + mode_list = 0; + + grub_video_fb_fini (); + return GRUB_ERR_NONE; }