2 * GRUB -- GRand Unified Bootloader
3 * Copyright (C) 2005,2006,2007,2008 Free Software Foundation, Inc.
5 * GRUB is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * GRUB is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with GRUB. If not, see <http://www.gnu.org/licenses/>.
20 #include <grub/machine/memory.h>
21 #include <grub/machine/vga.h>
22 #include <grub/machine/vbe.h>
23 #include <grub/machine/vbeblit.h>
24 #include <grub/machine/vbefill.h>
25 #include <grub/machine/vbeutil.h>
26 #include <grub/types.h>
28 #include <grub/misc.h>
29 #include <grub/font.h>
31 #include <grub/video.h>
32 #include <grub/bitmap.h>
34 /* Specify "standard" VGA palette, some video cards may
35 need this and this will also be used when using RGB modes. */
36 static struct grub_vbe_palette_data vga_colors
[16] =
39 {0x00, 0x00, 0x00, 0x00}, // 0 = black
40 {0xA8, 0x00, 0x00, 0x00}, // 1 = blue
41 {0x00, 0xA8, 0x00, 0x00}, // 2 = green
42 {0xA8, 0xA8, 0x00, 0x00}, // 3 = cyan
43 {0x00, 0x00, 0xA8, 0x00}, // 4 = red
44 {0xA8, 0x00, 0xA8, 0x00}, // 5 = magenta
45 {0x00, 0x54, 0xA8, 0x00}, // 6 = brown
46 {0xA8, 0xA8, 0xA8, 0x00}, // 7 = ligth gray
48 {0x54, 0x54, 0x54, 0x00}, // 8 = dark gray
49 {0xFE, 0x54, 0x54, 0x00}, // 9 = bright blue
50 {0x54, 0xFE, 0x54, 0x00}, // 10 = bright green
51 {0xFE, 0xFE, 0x54, 0x00}, // 11 = bright cyan
52 {0x54, 0x54, 0xFE, 0x00}, // 12 = bright red
53 {0xFE, 0x54, 0xFE, 0x00}, // 13 = bright magenta
54 {0x54, 0xFE, 0xFE, 0x00}, // 14 = yellow
55 {0xFE, 0xFE, 0xFE, 0x00} // 15 = white
58 static int vbe_detected
= -1;
60 static struct grub_vbe_info_block controller_info
;
61 static struct grub_vbe_mode_info_block active_mode_info
;
65 struct grub_video_render_target render_target
;
67 unsigned int bytes_per_scan_line
;
68 unsigned int bytes_per_pixel
;
69 grub_uint32_t active_mode
;
72 struct grub_video_palette_data palette
[256];
75 static struct grub_video_render_target
*render_target
;
76 static grub_uint32_t initial_mode
;
77 static grub_uint32_t mode_in_use
= 0x55aa;
78 static grub_uint16_t
*mode_list
;
81 real2pm (grub_vbe_farptr_t ptr
)
83 return (void *) ((((unsigned long) ptr
& 0xFFFF0000) >> 12UL)
84 + ((unsigned long) ptr
& 0x0000FFFF));
88 grub_vbe_probe (struct grub_vbe_info_block
*info_block
)
90 struct grub_vbe_info_block
*vbe_ib
;
91 grub_vbe_status_t status
;
93 /* Clear caller's controller info block. */
95 grub_memset (info_block
, 0, sizeof (*info_block
));
97 /* Do not probe more than one time, if not necessary. */
98 if (vbe_detected
== -1 || info_block
)
100 /* Clear old copy of controller info block. */
101 grub_memset (&controller_info
, 0, sizeof (controller_info
));
103 /* Mark VESA BIOS extension as undetected. */
106 /* Use low memory scratch area as temporary storage
107 for VESA BIOS call. */
108 vbe_ib
= (struct grub_vbe_info_block
*) GRUB_MEMORY_MACHINE_SCRATCH_ADDR
;
110 /* Prepare info block. */
111 grub_memset (vbe_ib
, 0, sizeof (*vbe_ib
));
113 vbe_ib
->signature
[0] = 'V';
114 vbe_ib
->signature
[1] = 'B';
115 vbe_ib
->signature
[2] = 'E';
116 vbe_ib
->signature
[3] = '2';
118 /* Try to get controller info block. */
119 status
= grub_vbe_bios_get_controller_info (vbe_ib
);
120 if (status
== 0x004F)
122 /* Copy it for later usage. */
123 grub_memcpy (&controller_info
, vbe_ib
, sizeof (controller_info
));
125 /* Mark VESA BIOS extension as detected. */
131 return grub_error (GRUB_ERR_BAD_DEVICE
, "VESA BIOS Extension not found");
133 /* Make copy of controller info block to caller. */
135 grub_memcpy (info_block
, &controller_info
, sizeof (*info_block
));
137 return GRUB_ERR_NONE
;
141 grub_vbe_set_video_mode (grub_uint32_t mode
,
142 struct grub_vbe_mode_info_block
*mode_info
)
144 grub_vbe_status_t status
;
145 grub_uint32_t old_mode
;
147 /* Make sure that VBE is supported. */
149 if (grub_errno
!= GRUB_ERR_NONE
)
152 /* Try to get mode info. */
153 grub_vbe_get_video_mode_info (mode
, &active_mode_info
);
154 if (grub_errno
!= GRUB_ERR_NONE
)
157 /* For all VESA BIOS modes, force linear frame buffer. */
160 /* We only want linear frame buffer modes. */
163 /* Determine frame buffer pixel format. */
164 switch (active_mode_info
.memory_model
)
166 case GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL
:
167 framebuffer
.index_color_mode
= 1;
170 case GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR
:
171 framebuffer
.index_color_mode
= 0;
175 return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET
,
176 "unsupported pixel format 0x%x",
177 active_mode_info
.memory_model
);
181 /* Get current mode. */
182 grub_vbe_get_video_mode (&old_mode
);
183 if (grub_errno
!= GRUB_ERR_NONE
)
186 /* Try to set video mode. */
187 status
= grub_vbe_bios_set_mode (mode
, 0);
188 if (status
!= GRUB_VBE_STATUS_OK
)
189 return grub_error (GRUB_ERR_BAD_DEVICE
, "cannot set VBE mode %x", mode
);
191 /* Save information for later usage. */
192 framebuffer
.active_mode
= mode
;
196 /* If this is not a VESA mode, guess address. */
197 framebuffer
.ptr
= (grub_uint8_t
*) GRUB_MEMORY_MACHINE_VGA_ADDR
;
198 framebuffer
.index_color_mode
= 1;
202 framebuffer
.ptr
= (grub_uint8_t
*) active_mode_info
.phys_base_addr
;
204 if (controller_info
.version
>= 0x300)
205 framebuffer
.bytes_per_scan_line
= active_mode_info
.lin_bytes_per_scan_line
;
207 framebuffer
.bytes_per_scan_line
= active_mode_info
.bytes_per_scan_line
;
210 /* Calculate bytes_per_pixel value. */
211 switch(active_mode_info
.bits_per_pixel
)
213 case 32: framebuffer
.bytes_per_pixel
= 4; break;
214 case 24: framebuffer
.bytes_per_pixel
= 3; break;
215 case 16: framebuffer
.bytes_per_pixel
= 2; break;
216 case 15: framebuffer
.bytes_per_pixel
= 2; break;
217 case 8: framebuffer
.bytes_per_pixel
= 1; break;
219 grub_vbe_bios_set_mode (old_mode
, 0);
220 return grub_error (GRUB_ERR_BAD_DEVICE
,
221 "cannot set VBE mode %x",
226 /* If video mode is in indexed color, setup default VGA palette. */
227 if (framebuffer
.index_color_mode
)
229 struct grub_vbe_palette_data
*palette
230 = (struct grub_vbe_palette_data
*) GRUB_MEMORY_MACHINE_SCRATCH_ADDR
;
232 /* Make sure that the BIOS can reach the palette. */
233 grub_memcpy (palette
, vga_colors
, sizeof (vga_colors
));
234 status
= grub_vbe_bios_set_palette_data (sizeof (vga_colors
)
235 / sizeof (struct grub_vbe_palette_data
),
239 /* Just ignore the status. */
242 /* Copy mode info for caller. */
244 grub_memcpy (mode_info
, &active_mode_info
, sizeof (*mode_info
));
246 return GRUB_ERR_NONE
;
250 grub_vbe_get_video_mode (grub_uint32_t
*mode
)
252 grub_vbe_status_t status
;
254 /* Make sure that VBE is supported. */
256 if (grub_errno
!= GRUB_ERR_NONE
)
259 /* Try to query current mode from VESA BIOS. */
260 status
= grub_vbe_bios_get_mode (mode
);
261 if (status
!= GRUB_VBE_STATUS_OK
)
262 return grub_error (GRUB_ERR_BAD_DEVICE
, "cannot get current VBE mode");
264 return GRUB_ERR_NONE
;
268 grub_vbe_get_video_mode_info (grub_uint32_t mode
,
269 struct grub_vbe_mode_info_block
*mode_info
)
271 struct grub_vbe_mode_info_block
*mi_tmp
272 = (struct grub_vbe_mode_info_block
*) GRUB_MEMORY_MACHINE_SCRATCH_ADDR
;
273 grub_vbe_status_t status
;
275 /* Make sure that VBE is supported. */
277 if (grub_errno
!= GRUB_ERR_NONE
)
280 /* If mode is not VESA mode, skip mode info query. */
283 /* Try to get mode info from VESA BIOS. */
284 status
= grub_vbe_bios_get_mode_info (mode
, mi_tmp
);
285 if (status
!= GRUB_VBE_STATUS_OK
)
286 return grub_error (GRUB_ERR_BAD_DEVICE
,
287 "cannot get information on the mode %x", mode
);
289 /* Make copy of mode info block. */
290 grub_memcpy (mode_info
, mi_tmp
, sizeof (*mode_info
));
293 /* Just clear mode info block if it isn't a VESA mode. */
294 grub_memset (mode_info
, 0, sizeof (*mode_info
));
296 return GRUB_ERR_NONE
;
300 grub_video_vbe_get_video_ptr (struct grub_video_i386_vbeblit_info
*source
,
301 grub_uint32_t x
, grub_uint32_t y
)
303 grub_uint8_t
*ptr
= 0;
305 switch (source
->mode_info
->bpp
)
308 ptr
= (grub_uint8_t
*)source
->data
309 + y
* source
->mode_info
->pitch
314 ptr
= (grub_uint8_t
*)source
->data
315 + y
* source
->mode_info
->pitch
321 ptr
= (grub_uint8_t
*)source
->data
322 + y
* source
->mode_info
->pitch
327 ptr
= (grub_uint8_t
*)source
->data
328 + y
* source
->mode_info
->pitch
337 grub_video_vbe_init (void)
339 grub_uint16_t
*rm_mode_list
;
341 grub_size_t mode_list_size
;
342 struct grub_vbe_info_block info_block
;
344 /* Check if there is adapter present.
346 Firmware note: There has been a report that some cards store video mode
347 list in temporary memory. So we must first use vbe probe to get
348 refreshed information to receive valid pointers and data, and then
349 copy this information to somewhere safe. */
350 grub_vbe_probe (&info_block
);
351 if (grub_errno
!= GRUB_ERR_NONE
)
354 /* Copy modelist to local memory. */
355 p
= rm_mode_list
= real2pm (info_block
.video_mode_ptr
);
356 while(*p
++ != 0xFFFF)
359 mode_list_size
= (grub_addr_t
) p
- (grub_addr_t
) rm_mode_list
;
360 mode_list
= grub_malloc (mode_list_size
);
363 grub_memcpy (mode_list
, rm_mode_list
, mode_list_size
);
365 /* Adapter could be found, figure out initial video mode. */
366 grub_vbe_get_video_mode (&initial_mode
);
367 if (grub_errno
!= GRUB_ERR_NONE
)
369 /* Free allocated resources. */
370 grub_free (mode_list
);
376 /* Reset frame buffer and render target variables. */
377 grub_memset (&framebuffer
, 0, sizeof(framebuffer
));
378 render_target
= &framebuffer
.render_target
;
380 return GRUB_ERR_NONE
;
384 grub_video_vbe_fini (void)
386 grub_vbe_status_t status
;
388 /* Restore old video mode. */
389 status
= grub_vbe_bios_set_mode (initial_mode
, 0);
390 if (status
!= GRUB_VBE_STATUS_OK
)
391 /* TODO: Decide, is this something we want to do. */
394 /* TODO: Free any resources allocated by driver. */
395 grub_free (mode_list
);
398 /* TODO: destroy render targets. */
400 /* Return success to caller. */
401 return GRUB_ERR_NONE
;
405 grub_video_vbe_setup (unsigned int width
, unsigned int height
,
406 unsigned int mode_type
)
409 struct grub_vbe_mode_info_block mode_info
;
410 struct grub_vbe_mode_info_block best_mode_info
;
411 grub_uint32_t best_mode
= 0;
415 /* Decode depth from mode_type. If it is zero, then autodetect. */
416 depth
= (mode_type
& GRUB_VIDEO_MODE_TYPE_DEPTH_MASK
)
417 >> GRUB_VIDEO_MODE_TYPE_DEPTH_POS
;
419 /* Walk thru mode list and try to find matching mode. */
420 for (p
= mode_list
; *p
!= 0xFFFF; p
++)
422 grub_uint32_t mode
= *p
;
424 grub_vbe_get_video_mode_info (mode
, &mode_info
);
425 if (grub_errno
!= GRUB_ERR_NONE
)
427 /* Could not retrieve mode info, retreat. */
428 grub_errno
= GRUB_ERR_NONE
;
432 if ((mode_info
.mode_attributes
& 0x001) == 0)
433 /* If not available, skip it. */
436 if ((mode_info
.mode_attributes
& 0x002) == 0)
437 /* Not enough information. */
440 if ((mode_info
.mode_attributes
& 0x008) == 0)
441 /* Monochrome is unusable. */
444 if ((mode_info
.mode_attributes
& 0x080) == 0)
445 /* We support only linear frame buffer modes. */
448 if ((mode_info
.mode_attributes
& 0x010) == 0)
449 /* We allow only graphical modes. */
452 if ((mode_info
.memory_model
!= GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL
)
453 && (mode_info
.memory_model
!= GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR
))
454 /* Not compatible memory model. */
457 if ((mode_info
.x_resolution
!= width
)
458 || (mode_info
.y_resolution
!= height
))
459 /* Non matching resolution. */
462 /* Check if user requested RGB or index color mode. */
463 if ((mode_type
& GRUB_VIDEO_MODE_TYPE_COLOR_MASK
) != 0)
465 if (((mode_type
& GRUB_VIDEO_MODE_TYPE_INDEX_COLOR
) != 0)
466 && (mode_info
.memory_model
!= GRUB_VBE_MEMORY_MODEL_PACKED_PIXEL
))
467 /* Requested only index color modes. */
470 if (((mode_type
& GRUB_VIDEO_MODE_TYPE_RGB
) != 0)
471 && (mode_info
.memory_model
!= GRUB_VBE_MEMORY_MODEL_DIRECT_COLOR
))
472 /* Requested only RGB modes. */
476 /* If there is a request for specific depth, ignore others. */
477 if ((depth
!= 0) && (mode_info
.bits_per_pixel
!= depth
))
480 /* Select mode with most number of bits per pixel. */
482 if (mode_info
.bits_per_pixel
< best_mode_info
.bits_per_pixel
)
485 /* Save so far best mode information for later use. */
487 grub_memcpy (&best_mode_info
, &mode_info
, sizeof (mode_info
));
490 /* Try to initialize best mode found. */
493 /* If this fails, then we have mode selection heuristics problem,
494 or adapter failure. */
495 grub_vbe_set_video_mode (best_mode
, &active_mode_info
);
496 if (grub_errno
!= GRUB_ERR_NONE
)
499 /* Now we are happily in requested video mode. Cache some info
500 in order to fasten later operations. */
501 mode_in_use
= best_mode
;
503 /* Reset render target to framebuffer one. */
504 render_target
= &framebuffer
.render_target
;
506 /* Fill mode info details in framebuffer's render target. */
507 render_target
->mode_info
.width
= active_mode_info
.x_resolution
;
508 render_target
->mode_info
.height
= active_mode_info
.y_resolution
;
510 if (framebuffer
.index_color_mode
)
511 render_target
->mode_info
.mode_type
= GRUB_VIDEO_MODE_TYPE_INDEX_COLOR
;
513 render_target
->mode_info
.mode_type
= GRUB_VIDEO_MODE_TYPE_RGB
;
515 render_target
->mode_info
.bpp
= active_mode_info
.bits_per_pixel
;
516 render_target
->mode_info
.bytes_per_pixel
= framebuffer
.bytes_per_pixel
;
517 render_target
->mode_info
.pitch
= framebuffer
.bytes_per_scan_line
;
518 render_target
->mode_info
.number_of_colors
= 256; /* TODO: fix me. */
519 render_target
->mode_info
.red_mask_size
= active_mode_info
.red_mask_size
;
520 render_target
->mode_info
.red_field_pos
= active_mode_info
.red_field_position
;
521 render_target
->mode_info
.green_mask_size
= active_mode_info
.green_mask_size
;
522 render_target
->mode_info
.green_field_pos
= active_mode_info
.green_field_position
;
523 render_target
->mode_info
.blue_mask_size
= active_mode_info
.blue_mask_size
;
524 render_target
->mode_info
.blue_field_pos
= active_mode_info
.blue_field_position
;
525 render_target
->mode_info
.reserved_mask_size
= active_mode_info
.rsvd_mask_size
;
526 render_target
->mode_info
.reserved_field_pos
= active_mode_info
.rsvd_field_position
;
528 render_target
->mode_info
.blit_format
= grub_video_get_blit_format (&render_target
->mode_info
);
530 /* Reset viewport to match new mode. */
531 render_target
->viewport
.x
= 0;
532 render_target
->viewport
.y
= 0;
533 render_target
->viewport
.width
= active_mode_info
.x_resolution
;
534 render_target
->viewport
.height
= active_mode_info
.y_resolution
;
536 /* Set framebuffer pointer and mark it as non allocated. */
537 render_target
->is_allocated
= 0;
538 render_target
->data
= framebuffer
.ptr
;
540 /* Copy default palette to initialize emulated palette. */
542 i
< (sizeof (vga_colors
)
543 / sizeof (struct grub_vbe_palette_data
));
546 framebuffer
.palette
[i
].r
= vga_colors
[i
].red
;
547 framebuffer
.palette
[i
].g
= vga_colors
[i
].green
;
548 framebuffer
.palette
[i
].b
= vga_colors
[i
].blue
;
549 framebuffer
.palette
[i
].a
= 0xFF;
552 return GRUB_ERR_NONE
;
555 /* Couldn't found matching mode. */
556 return grub_error (GRUB_ERR_UNKNOWN_DEVICE
, "no matching mode found.");
560 grub_video_vbe_get_info (struct grub_video_mode_info
*mode_info
)
562 /* Copy mode info from active render target. */
563 grub_memcpy (mode_info
, &render_target
->mode_info
,
564 sizeof (struct grub_video_mode_info
));
566 return GRUB_ERR_NONE
;
570 grub_video_vbe_set_palette (unsigned int start
, unsigned int count
,
571 struct grub_video_palette_data
*palette_data
)
575 if (framebuffer
.index_color_mode
)
577 /* TODO: Implement setting indexed color mode palette to hardware. */
578 //status = grub_vbe_bios_set_palette_data (sizeof (vga_colors)
579 // / sizeof (struct grub_vbe_palette_data),
585 /* Then set color to emulated palette. */
586 for (i
= 0; (i
< count
) && ((i
+ start
) < 256); i
++)
587 framebuffer
.palette
[start
+ i
] = palette_data
[i
];
589 return GRUB_ERR_NONE
;
593 grub_video_vbe_get_palette (unsigned int start
, unsigned int count
,
594 struct grub_video_palette_data
*palette_data
)
598 /* Assume that we know everything from index color palette. */
599 for (i
= 0; (i
< count
) && ((i
+ start
) < 256); i
++)
600 palette_data
[i
] = framebuffer
.palette
[start
+ i
];
602 return GRUB_ERR_NONE
;
606 grub_video_vbe_set_viewport (unsigned int x
, unsigned int y
,
607 unsigned int width
, unsigned int height
)
609 /* Make sure viewport is withing screen dimensions. If viewport was set
610 to be out of the region, mark its size as zero. */
611 if (x
> active_mode_info
.x_resolution
)
617 if (y
> active_mode_info
.y_resolution
)
623 if (x
+ width
> active_mode_info
.x_resolution
)
624 width
= active_mode_info
.x_resolution
- x
;
626 if (y
+ height
> active_mode_info
.y_resolution
)
627 height
= active_mode_info
.y_resolution
- y
;
629 render_target
->viewport
.x
= x
;
630 render_target
->viewport
.y
= y
;
631 render_target
->viewport
.width
= width
;
632 render_target
->viewport
.height
= height
;
634 return GRUB_ERR_NONE
;
638 grub_video_vbe_get_viewport (unsigned int *x
, unsigned int *y
,
639 unsigned int *width
, unsigned int *height
)
641 if (x
) *x
= render_target
->viewport
.x
;
642 if (y
) *y
= render_target
->viewport
.y
;
643 if (width
) *width
= render_target
->viewport
.width
;
644 if (height
) *height
= render_target
->viewport
.height
;
646 return GRUB_ERR_NONE
;
649 /* Maps color name to target optimized color format. */
650 static grub_video_color_t
651 grub_video_vbe_map_color (grub_uint32_t color_name
)
653 /* TODO: implement color theme mapping code. */
655 if (color_name
< 256)
657 if ((render_target
->mode_info
.mode_type
658 & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR
) != 0)
662 grub_video_color_t color
;
664 color
= grub_video_vbe_map_rgb (framebuffer
.palette
[color_name
].r
,
665 framebuffer
.palette
[color_name
].g
,
666 framebuffer
.palette
[color_name
].b
);
675 /* Maps RGB to target optimized color format. */
677 grub_video_vbe_map_rgb (grub_uint8_t red
, grub_uint8_t green
,
680 if ((render_target
->mode_info
.mode_type
681 & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR
) != 0)
689 /* Find best matching color. */
690 for (i
= 0; i
< 256; i
++)
692 val
= framebuffer
.palette
[i
].r
- red
;
694 val
= framebuffer
.palette
[i
].g
- green
;
696 val
= framebuffer
.palette
[i
].b
- blue
;
716 grub_uint8_t alpha
= 255; /* Opaque color. */
718 red
>>= 8 - render_target
->mode_info
.red_mask_size
;
719 green
>>= 8 - render_target
->mode_info
.green_mask_size
;
720 blue
>>= 8 - render_target
->mode_info
.blue_mask_size
;
721 alpha
>>= 8 - render_target
->mode_info
.reserved_mask_size
;
723 value
= red
<< render_target
->mode_info
.red_field_pos
;
724 value
|= green
<< render_target
->mode_info
.green_field_pos
;
725 value
|= blue
<< render_target
->mode_info
.blue_field_pos
;
726 value
|= alpha
<< render_target
->mode_info
.reserved_field_pos
;
733 /* Maps RGBA to target optimized color format. */
735 grub_video_vbe_map_rgba (grub_uint8_t red
, grub_uint8_t green
,
736 grub_uint8_t blue
, grub_uint8_t alpha
)
738 if ((render_target
->mode_info
.mode_type
739 & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR
) != 0)
740 /* No alpha available in index color modes, just use
741 same value as in only RGB modes. */
742 return grub_video_vbe_map_rgb (red
, green
, blue
);
747 red
>>= 8 - render_target
->mode_info
.red_mask_size
;
748 green
>>= 8 - render_target
->mode_info
.green_mask_size
;
749 blue
>>= 8 - render_target
->mode_info
.blue_mask_size
;
750 alpha
>>= 8 - render_target
->mode_info
.reserved_mask_size
;
752 value
= red
<< render_target
->mode_info
.red_field_pos
;
753 value
|= green
<< render_target
->mode_info
.green_field_pos
;
754 value
|= blue
<< render_target
->mode_info
.blue_field_pos
;
755 value
|= alpha
<< render_target
->mode_info
.reserved_field_pos
;
761 /* Splits target optimized format to components. */
762 grub_err_t
grub_video_vbe_unmap_color (grub_video_color_t color
,
763 grub_uint8_t
*red
, grub_uint8_t
*green
,
764 grub_uint8_t
*blue
, grub_uint8_t
*alpha
)
766 struct grub_video_i386_vbeblit_info target_info
;
768 target_info
.mode_info
= &render_target
->mode_info
;
769 target_info
.data
= render_target
->data
;
771 grub_video_vbe_unmap_color_int (&target_info
, color
, red
, green
, blue
, alpha
);
773 return GRUB_ERR_NONE
;
776 /* Splits color in source format to components. */
778 grub_video_vbe_unmap_color_int (struct grub_video_i386_vbeblit_info
* source
,
779 grub_video_color_t color
,
780 grub_uint8_t
*red
, grub_uint8_t
*green
,
781 grub_uint8_t
*blue
, grub_uint8_t
*alpha
)
783 struct grub_video_mode_info
*mode_info
;
784 mode_info
= source
->mode_info
;
786 if ((mode_info
->mode_type
787 & GRUB_VIDEO_MODE_TYPE_INDEX_COLOR
) != 0)
789 /* If we have an out-of-bounds color, return transparent black. */
799 *red
= framebuffer
.palette
[color
].r
;
800 *green
= framebuffer
.palette
[color
].g
;
801 *blue
= framebuffer
.palette
[color
].b
;
802 *alpha
= framebuffer
.palette
[color
].a
;
809 /* Get red component. */
810 tmp
= color
>> mode_info
->red_field_pos
;
811 tmp
&= (1 << mode_info
->red_mask_size
) - 1;
812 tmp
<<= 8 - mode_info
->red_mask_size
;
813 tmp
|= (1 << (8 - mode_info
->red_mask_size
)) - 1;
816 /* Get green component. */
817 tmp
= color
>> mode_info
->green_field_pos
;
818 tmp
&= (1 << mode_info
->green_mask_size
) - 1;
819 tmp
<<= 8 - mode_info
->green_mask_size
;
820 tmp
|= (1 << (8 - mode_info
->green_mask_size
)) - 1;
823 /* Get blue component. */
824 tmp
= color
>> mode_info
->blue_field_pos
;
825 tmp
&= (1 << mode_info
->blue_mask_size
) - 1;
826 tmp
<<= 8 - mode_info
->blue_mask_size
;
827 tmp
|= (1 << (8 - mode_info
->blue_mask_size
)) - 1;
830 /* Get alpha component. */
831 if (source
->mode_info
->reserved_mask_size
> 0)
833 tmp
= color
>> mode_info
->reserved_field_pos
;
834 tmp
&= (1 << mode_info
->reserved_mask_size
) - 1;
835 tmp
<<= 8 - mode_info
->reserved_mask_size
;
836 tmp
|= (1 << (8 - mode_info
->reserved_mask_size
)) - 1;
839 /* If there is no alpha component, assume it opaque. */
847 grub_video_vbe_fill_rect (grub_video_color_t color
, int x
, int y
,
848 unsigned int width
, unsigned int height
)
850 struct grub_video_i386_vbeblit_info target
;
852 /* Make sure there is something to do. */
853 if ((x
>= (int)render_target
->viewport
.width
) || (x
+ (int)width
< 0))
854 return GRUB_ERR_NONE
;
855 if ((y
>= (int)render_target
->viewport
.height
) || (y
+ (int)height
< 0))
856 return GRUB_ERR_NONE
;
858 /* Do not allow drawing out of viewport. */
870 if ((x
+ width
) > render_target
->viewport
.width
)
871 width
= render_target
->viewport
.width
- x
;
872 if ((y
+ height
) > render_target
->viewport
.height
)
873 height
= render_target
->viewport
.height
- y
;
875 /* Add viewport offset. */
876 x
+= render_target
->viewport
.x
;
877 y
+= render_target
->viewport
.y
;
879 /* Use vbeblit_info to encapsulate rendering. */
880 target
.mode_info
= &render_target
->mode_info
;
881 target
.data
= render_target
->data
;
883 /* Try to figure out more optimized version. Note that color is already
884 mapped to target format so we can make assumptions based on that. */
885 if (target
.mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_BGRA_8888
)
887 grub_video_i386_vbefill_direct32 (&target
, color
, x
, y
,
889 return GRUB_ERR_NONE
;
891 else if (target
.mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_RGBA_8888
)
893 grub_video_i386_vbefill_direct32 (&target
, color
, x
, y
,
895 return GRUB_ERR_NONE
;
897 else if (target
.mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_RGB_888
)
899 grub_video_i386_vbefill_direct24 (&target
, color
, x
, y
,
901 return GRUB_ERR_NONE
;
903 else if (target
.mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_RGB_565
)
905 grub_video_i386_vbefill_direct16 (&target
, color
, x
, y
,
907 return GRUB_ERR_NONE
;
909 else if (target
.mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_BGR_565
)
911 grub_video_i386_vbefill_direct16 (&target
, color
, x
, y
,
913 return GRUB_ERR_NONE
;
915 else if (target
.mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR
)
917 grub_video_i386_vbefill_direct8 (&target
, color
, x
, y
,
919 return GRUB_ERR_NONE
;
922 /* No optimized version found, use default (slow) filler. */
923 grub_video_i386_vbefill (&target
, color
, x
, y
, width
, height
);
925 return GRUB_ERR_NONE
;
928 // TODO: Remove this method and replace with bitmap based glyphs
930 grub_video_vbe_blit_glyph (struct grub_font_glyph
* glyph
,
931 grub_video_color_t color
, int x
, int y
)
933 struct grub_video_i386_vbeblit_info target
;
935 unsigned int charwidth
;
939 unsigned int x_offset
= 0;
940 unsigned int y_offset
= 0;
942 /* Make sure there is something to do. */
943 if (x
>= (int)render_target
->viewport
.width
)
944 return GRUB_ERR_NONE
;
946 if (y
>= (int)render_target
->viewport
.height
)
947 return GRUB_ERR_NONE
;
949 /* Calculate glyph dimensions. */
950 width
= ((glyph
->width
+ 7) / 8) * 8;
952 height
= glyph
->height
;
954 if (x
+ (int)width
< 0)
955 return GRUB_ERR_NONE
;
957 if (y
+ (int)height
< 0)
958 return GRUB_ERR_NONE
;
960 /* Do not allow drawing out of viewport. */
964 x_offset
= (unsigned int)-x
;
970 y_offset
= (unsigned int)-y
;
974 if ((x
+ width
) > render_target
->viewport
.width
)
975 width
= render_target
->viewport
.width
- x
;
976 if ((y
+ height
) > render_target
->viewport
.height
)
977 height
= render_target
->viewport
.height
- y
;
979 /* Add viewport offset. */
980 x
+= render_target
->viewport
.x
;
981 y
+= render_target
->viewport
.y
;
983 /* Use vbeblit_info to encapsulate rendering. */
984 target
.mode_info
= &render_target
->mode_info
;
985 target
.data
= render_target
->data
;
988 for (j
= 0; j
< height
; j
++)
989 for (i
= 0; i
< width
; i
++)
990 if ((glyph
->bitmap
[((i
+ x_offset
) / 8)
991 + (j
+ y_offset
) * (charwidth
/ 8)]
992 & (1 << ((charwidth
- (i
+ x_offset
) - 1) % 8))))
993 set_pixel (&target
, x
+i
, y
+j
, color
);
995 return GRUB_ERR_NONE
;
998 /* NOTE: This function assumes that given coordinates are within bounds of
1001 common_blitter (struct grub_video_i386_vbeblit_info
*target
,
1002 struct grub_video_i386_vbeblit_info
*source
,
1003 enum grub_video_blit_operators oper
, int x
, int y
,
1004 unsigned int width
, unsigned int height
,
1005 int offset_x
, int offset_y
)
1007 if (oper
== GRUB_VIDEO_BLIT_REPLACE
)
1009 /* Try to figure out more optimized version for replace operator. */
1010 if (source
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_RGBA_8888
)
1012 if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_RGBA_8888
)
1014 grub_video_i386_vbeblit_replace_directN (target
, source
,
1015 x
, y
, width
, height
,
1016 offset_x
, offset_y
);
1019 else if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_BGRA_8888
)
1021 grub_video_i386_vbeblit_replace_BGRX8888_RGBX8888 (target
, source
,
1022 x
, y
, width
, height
,
1023 offset_x
, offset_y
);
1026 else if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_BGR_888
)
1028 grub_video_i386_vbeblit_replace_BGR888_RGBX8888 (target
, source
,
1029 x
, y
, width
, height
,
1030 offset_x
, offset_y
);
1033 else if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_RGB_888
)
1035 grub_video_i386_vbeblit_replace_RGB888_RGBX8888 (target
, source
,
1036 x
, y
, width
, height
,
1037 offset_x
, offset_y
);
1040 else if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR
)
1042 grub_video_i386_vbeblit_replace_index_RGBX8888 (target
, source
,
1043 x
, y
, width
, height
,
1044 offset_x
, offset_y
);
1048 else if (source
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_RGB_888
)
1050 if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_BGRA_8888
)
1052 grub_video_i386_vbeblit_replace_BGRX8888_RGB888 (target
, source
,
1053 x
, y
, width
, height
,
1054 offset_x
, offset_y
);
1057 else if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_RGBA_8888
)
1059 grub_video_i386_vbeblit_replace_RGBX8888_RGB888 (target
, source
,
1060 x
, y
, width
, height
,
1061 offset_x
, offset_y
);
1064 else if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_BGR_888
)
1066 grub_video_i386_vbeblit_replace_BGR888_RGB888 (target
, source
,
1067 x
, y
, width
, height
,
1068 offset_x
, offset_y
);
1071 else if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_RGB_888
)
1073 grub_video_i386_vbeblit_replace_directN (target
, source
,
1074 x
, y
, width
, height
,
1075 offset_x
, offset_y
);
1078 else if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR
)
1080 grub_video_i386_vbeblit_replace_index_RGB888 (target
, source
,
1081 x
, y
, width
, height
,
1082 offset_x
, offset_y
);
1086 else if (source
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_BGRA_8888
)
1088 if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_BGRA_8888
)
1090 grub_video_i386_vbeblit_replace_directN (target
, source
,
1091 x
, y
, width
, height
,
1092 offset_x
, offset_y
);
1096 else if (source
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR
)
1098 if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR
)
1100 grub_video_i386_vbeblit_replace_directN (target
, source
,
1101 x
, y
, width
, height
,
1102 offset_x
, offset_y
);
1107 /* No optimized replace operator found, use default (slow) blitter. */
1108 grub_video_i386_vbeblit_replace (target
, source
, x
, y
, width
, height
,
1109 offset_x
, offset_y
);
1113 /* Try to figure out more optimized blend operator. */
1114 if (source
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_RGBA_8888
)
1116 if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_BGRA_8888
)
1118 grub_video_i386_vbeblit_blend_BGRA8888_RGBA8888 (target
, source
,
1119 x
, y
, width
, height
,
1120 offset_x
, offset_y
);
1123 else if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_RGBA_8888
)
1125 grub_video_i386_vbeblit_blend_RGBA8888_RGBA8888 (target
, source
,
1126 x
, y
, width
, height
,
1127 offset_x
, offset_y
);
1130 else if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_BGR_888
)
1132 grub_video_i386_vbeblit_blend_BGR888_RGBA8888 (target
, source
,
1133 x
, y
, width
, height
,
1134 offset_x
, offset_y
);
1137 else if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_RGB_888
)
1139 grub_video_i386_vbeblit_blend_RGB888_RGBA8888 (target
, source
,
1140 x
, y
, width
, height
,
1141 offset_x
, offset_y
);
1144 else if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR
)
1146 grub_video_i386_vbeblit_blend_index_RGBA8888 (target
, source
,
1147 x
, y
, width
, height
,
1148 offset_x
, offset_y
);
1152 else if (source
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_RGB_888
)
1154 /* Note: There is really no alpha information here, so blend is
1155 changed to replace. */
1157 if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_BGRA_8888
)
1159 grub_video_i386_vbeblit_replace_BGRX8888_RGB888 (target
, source
,
1160 x
, y
, width
, height
,
1161 offset_x
, offset_y
);
1164 else if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_RGBA_8888
)
1166 grub_video_i386_vbeblit_replace_RGBX8888_RGB888 (target
, source
,
1167 x
, y
, width
, height
,
1168 offset_x
, offset_y
);
1171 else if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_BGR_888
)
1173 grub_video_i386_vbeblit_replace_BGR888_RGB888 (target
, source
,
1174 x
, y
, width
, height
,
1175 offset_x
, offset_y
);
1178 else if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_RGB_888
)
1180 grub_video_i386_vbeblit_replace_directN (target
, source
,
1181 x
, y
, width
, height
,
1182 offset_x
, offset_y
);
1185 else if (target
->mode_info
->blit_format
== GRUB_VIDEO_BLIT_FORMAT_INDEXCOLOR
)
1187 grub_video_i386_vbeblit_replace_index_RGB888 (target
, source
,
1188 x
, y
, width
, height
,
1189 offset_x
, offset_y
);
1194 /* No optimized blend operation found, use default (slow) blitter. */
1195 grub_video_i386_vbeblit_blend (target
, source
, x
, y
, width
, height
,
1196 offset_x
, offset_y
);
1201 grub_video_vbe_blit_bitmap (struct grub_video_bitmap
*bitmap
,
1202 enum grub_video_blit_operators oper
, int x
, int y
,
1203 int offset_x
, int offset_y
,
1204 unsigned int width
, unsigned int height
)
1206 struct grub_video_i386_vbeblit_info source
;
1207 struct grub_video_i386_vbeblit_info target
;
1209 /* Make sure there is something to do. */
1210 if ((width
== 0) || (height
== 0))
1211 return GRUB_ERR_NONE
;
1212 if ((x
>= (int)render_target
->viewport
.width
) || (x
+ (int)width
< 0))
1213 return GRUB_ERR_NONE
;
1214 if ((y
>= (int)render_target
->viewport
.height
) || (y
+ (int)height
< 0))
1215 return GRUB_ERR_NONE
;
1216 if ((x
+ (int)bitmap
->mode_info
.width
) < 0)
1217 return GRUB_ERR_NONE
;
1218 if ((y
+ (int)bitmap
->mode_info
.height
) < 0)
1219 return GRUB_ERR_NONE
;
1220 if ((offset_x
>= (int)bitmap
->mode_info
.width
)
1221 || (offset_x
+ (int)width
< 0))
1222 return GRUB_ERR_NONE
;
1223 if ((offset_y
>= (int)bitmap
->mode_info
.height
)
1224 || (offset_y
+ (int)height
< 0))
1225 return GRUB_ERR_NONE
;
1227 /* If we have negative coordinates, optimize drawing to minimum. */
1256 /* Do not allow drawing out of viewport. */
1257 if ((x
+ width
) > render_target
->viewport
.width
)
1258 width
= render_target
->viewport
.width
- x
;
1259 if ((y
+ height
) > render_target
->viewport
.height
)
1260 height
= render_target
->viewport
.height
- y
;
1262 if ((offset_x
+ width
) > bitmap
->mode_info
.width
)
1263 width
= bitmap
->mode_info
.width
- offset_x
;
1264 if ((offset_y
+ height
) > bitmap
->mode_info
.height
)
1265 height
= bitmap
->mode_info
.height
- offset_y
;
1267 /* Limit drawing to source render target dimensions. */
1268 if (width
> bitmap
->mode_info
.width
)
1269 width
= bitmap
->mode_info
.width
;
1271 if (height
> bitmap
->mode_info
.height
)
1272 height
= bitmap
->mode_info
.height
;
1274 /* Add viewport offset. */
1275 x
+= render_target
->viewport
.x
;
1276 y
+= render_target
->viewport
.y
;
1278 /* Use vbeblit_info to encapsulate rendering. */
1279 source
.mode_info
= &bitmap
->mode_info
;
1280 source
.data
= bitmap
->data
;
1281 target
.mode_info
= &render_target
->mode_info
;
1282 target
.data
= render_target
->data
;
1284 /* Do actual blitting. */
1285 common_blitter (&target
, &source
, oper
, x
, y
, width
, height
,
1286 offset_x
, offset_y
);
1288 return GRUB_ERR_NONE
;
1292 grub_video_vbe_blit_render_target (struct grub_video_render_target
*source
,
1293 enum grub_video_blit_operators oper
,
1294 int x
, int y
, int offset_x
, int offset_y
,
1295 unsigned int width
, unsigned int height
)
1297 struct grub_video_i386_vbeblit_info source_info
;
1298 struct grub_video_i386_vbeblit_info target_info
;
1300 /* Make sure there is something to do. */
1301 if ((width
== 0) || (height
== 0))
1302 return GRUB_ERR_NONE
;
1303 if ((x
>= (int)render_target
->viewport
.width
) || (x
+ (int)width
< 0))
1304 return GRUB_ERR_NONE
;
1305 if ((y
>= (int)render_target
->viewport
.height
) || (y
+ (int)height
< 0))
1306 return GRUB_ERR_NONE
;
1307 if ((x
+ (int)source
->mode_info
.width
) < 0)
1308 return GRUB_ERR_NONE
;
1309 if ((y
+ (int)source
->mode_info
.height
) < 0)
1310 return GRUB_ERR_NONE
;
1311 if ((offset_x
>= (int)source
->mode_info
.width
)
1312 || (offset_x
+ (int)width
< 0))
1313 return GRUB_ERR_NONE
;
1314 if ((offset_y
>= (int)source
->mode_info
.height
)
1315 || (offset_y
+ (int)height
< 0))
1316 return GRUB_ERR_NONE
;
1318 /* If we have negative coordinates, optimize drawing to minimum. */
1347 /* Do not allow drawing out of viewport. */
1348 if ((x
+ width
) > render_target
->viewport
.width
)
1349 width
= render_target
->viewport
.width
- x
;
1350 if ((y
+ height
) > render_target
->viewport
.height
)
1351 height
= render_target
->viewport
.height
- y
;
1353 if ((offset_x
+ width
) > source
->mode_info
.width
)
1354 width
= source
->mode_info
.width
- offset_x
;
1355 if ((offset_y
+ height
) > source
->mode_info
.height
)
1356 height
= source
->mode_info
.height
- offset_y
;
1358 /* Limit drawing to source render target dimensions. */
1359 if (width
> source
->mode_info
.width
)
1360 width
= source
->mode_info
.width
;
1362 if (height
> source
->mode_info
.height
)
1363 height
= source
->mode_info
.height
;
1365 /* Add viewport offset. */
1366 x
+= render_target
->viewport
.x
;
1367 y
+= render_target
->viewport
.y
;
1369 /* Use vbeblit_info to encapsulate rendering. */
1370 source_info
.mode_info
= &source
->mode_info
;
1371 source_info
.data
= source
->data
;
1372 target_info
.mode_info
= &render_target
->mode_info
;
1373 target_info
.data
= render_target
->data
;
1375 /* Do actual blitting. */
1376 common_blitter (&target_info
, &source_info
, oper
, x
, y
, width
, height
,
1377 offset_x
, offset_y
);
1379 return GRUB_ERR_NONE
;
1383 grub_video_vbe_scroll (grub_video_color_t color
, int dx
, int dy
)
1392 /* 1. Check if we have something to do. */
1393 if ((dx
== 0) && (dy
== 0))
1394 return GRUB_ERR_NONE
;
1396 width
= render_target
->viewport
.width
- grub_abs (dx
);
1397 height
= render_target
->viewport
.height
- grub_abs (dy
);
1401 src_x
= render_target
->viewport
.x
- dx
;
1402 dst_x
= render_target
->viewport
.x
;
1406 src_x
= render_target
->viewport
.x
;
1407 dst_x
= render_target
->viewport
.x
+ dx
;
1412 src_y
= render_target
->viewport
.y
- dy
;
1413 dst_y
= render_target
->viewport
.y
;
1417 src_y
= render_target
->viewport
.y
;
1418 dst_y
= render_target
->viewport
.y
+ dy
;
1421 /* 2. Check if there is need to copy data. */
1422 if ((grub_abs (dx
) < render_target
->viewport
.width
)
1423 && (grub_abs (dy
) < render_target
->viewport
.height
))
1425 /* 3. Move data in render target. */
1426 struct grub_video_i386_vbeblit_info target
;
1431 target
.mode_info
= &render_target
->mode_info
;
1432 target
.data
= render_target
->data
;
1434 for (j
= 0; j
< height
; j
++)
1436 dst
= grub_video_vbe_get_video_ptr (&target
, dst_x
, dst_y
+ j
);
1437 src
= grub_video_vbe_get_video_ptr (&target
, src_x
, src_y
+ j
);
1438 grub_memmove (dst
, src
,
1439 width
* target
.mode_info
->bytes_per_pixel
);
1443 /* 4. Fill empty space with specified color. In this implementation
1444 there might be colliding areas but at the moment there is no need
1445 to optimize this. */
1447 /* 4a. Fill top & bottom parts. */
1449 grub_video_vbe_fill_rect (color
, 0, 0, render_target
->viewport
.width
, dy
);
1452 if (render_target
->viewport
.height
< grub_abs (dy
))
1453 dy
= -render_target
->viewport
.height
;
1455 grub_video_vbe_fill_rect (color
, 0, render_target
->viewport
.height
+ dy
,
1456 render_target
->viewport
.width
, -dy
);
1459 /* 4b. Fill left & right parts. */
1461 grub_video_vbe_fill_rect (color
, 0, 0,
1462 dx
, render_target
->viewport
.height
);
1465 if (render_target
->viewport
.width
< grub_abs (dx
))
1466 dx
= -render_target
->viewport
.width
;
1468 grub_video_vbe_fill_rect (color
, render_target
->viewport
.width
+ dx
, 0,
1469 -dx
, render_target
->viewport
.height
);
1472 return GRUB_ERR_NONE
;
1476 grub_video_vbe_swap_buffers (void)
1478 /* TODO: Implement buffer swapping. */
1479 return GRUB_ERR_NONE
;
1483 grub_video_vbe_create_render_target (struct grub_video_render_target
**result
,
1484 unsigned int width
, unsigned int height
,
1485 unsigned int mode_type
__attribute__ ((unused
)))
1487 struct grub_video_render_target
*target
;
1490 /* Validate arguments. */
1494 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
1495 "invalid argument given.");
1497 /* Allocate memory for render target. */
1498 target
= grub_malloc (sizeof (struct grub_video_render_target
));
1502 /* TODO: Implement other types too.
1503 Currently only 32bit render targets are supported. */
1505 /* Mark render target as allocated. */
1506 target
->is_allocated
= 1;
1508 /* Maximize viewport. */
1509 target
->viewport
.x
= 0;
1510 target
->viewport
.y
= 0;
1511 target
->viewport
.width
= width
;
1512 target
->viewport
.height
= height
;
1514 /* Setup render target format. */
1515 target
->mode_info
.width
= width
;
1516 target
->mode_info
.height
= height
;
1517 target
->mode_info
.mode_type
= GRUB_VIDEO_MODE_TYPE_RGB
1518 | GRUB_VIDEO_MODE_TYPE_ALPHA
;
1519 target
->mode_info
.bpp
= 32;
1520 target
->mode_info
.bytes_per_pixel
= 4;
1521 target
->mode_info
.pitch
= target
->mode_info
.bytes_per_pixel
* width
;
1522 target
->mode_info
.number_of_colors
= 256; /* Emulated palette. */
1523 target
->mode_info
.red_mask_size
= 8;
1524 target
->mode_info
.red_field_pos
= 0;
1525 target
->mode_info
.green_mask_size
= 8;
1526 target
->mode_info
.green_field_pos
= 8;
1527 target
->mode_info
.blue_mask_size
= 8;
1528 target
->mode_info
.blue_field_pos
= 16;
1529 target
->mode_info
.reserved_mask_size
= 8;
1530 target
->mode_info
.reserved_field_pos
= 24;
1532 target
->mode_info
.blit_format
= grub_video_get_blit_format (&target
->mode_info
);
1534 /* Calculate size needed for the data. */
1535 size
= (width
* target
->mode_info
.bytes_per_pixel
) * height
;
1537 target
->data
= grub_malloc (size
);
1544 /* Clear render target with black and maximum transparency. */
1545 grub_memset (target
->data
, 0, size
);
1547 /* TODO: Add render target to render target list. */
1549 /* Save result to caller. */
1552 return GRUB_ERR_NONE
;
1556 grub_video_vbe_delete_render_target (struct grub_video_render_target
*target
)
1558 /* If there is no target, then just return without error. */
1560 return GRUB_ERR_NONE
;
1562 /* TODO: Delist render target fron render target list. */
1564 /* If this is software render target, free it's memory. */
1565 if (target
->is_allocated
)
1566 grub_free (target
->data
);
1568 /* Free render target. */
1571 return GRUB_ERR_NONE
;
1575 grub_video_vbe_set_active_render_target (struct grub_video_render_target
*target
)
1577 if (target
== GRUB_VIDEO_RENDER_TARGET_FRONT_BUFFER
)
1579 render_target
= &framebuffer
.render_target
;
1581 return GRUB_ERR_NONE
;
1584 if (target
== GRUB_VIDEO_RENDER_TARGET_BACK_BUFFER
)
1585 return grub_error (GRUB_ERR_NOT_IMPLEMENTED_YET
,
1586 "double buffering not implemented yet.");
1589 return grub_error (GRUB_ERR_BAD_ARGUMENT
,
1590 "invalid render target given.");
1592 render_target
= target
;
1594 return GRUB_ERR_NONE
;
1598 grub_video_vbe_get_active_render_target (struct grub_video_render_target
**target
)
1600 *target
= render_target
;
1602 return GRUB_ERR_NONE
;
1605 static struct grub_video_adapter grub_video_vbe_adapter
=
1607 .name
= "VESA BIOS Extension Video Driver",
1609 .init
= grub_video_vbe_init
,
1610 .fini
= grub_video_vbe_fini
,
1611 .setup
= grub_video_vbe_setup
,
1612 .get_info
= grub_video_vbe_get_info
,
1613 .set_palette
= grub_video_vbe_set_palette
,
1614 .get_palette
= grub_video_vbe_get_palette
,
1615 .set_viewport
= grub_video_vbe_set_viewport
,
1616 .get_viewport
= grub_video_vbe_get_viewport
,
1617 .map_color
= grub_video_vbe_map_color
,
1618 .map_rgb
= grub_video_vbe_map_rgb
,
1619 .map_rgba
= grub_video_vbe_map_rgba
,
1620 .unmap_color
= grub_video_vbe_unmap_color
,
1621 .fill_rect
= grub_video_vbe_fill_rect
,
1622 .blit_glyph
= grub_video_vbe_blit_glyph
,
1623 .blit_bitmap
= grub_video_vbe_blit_bitmap
,
1624 .blit_render_target
= grub_video_vbe_blit_render_target
,
1625 .scroll
= grub_video_vbe_scroll
,
1626 .swap_buffers
= grub_video_vbe_swap_buffers
,
1627 .create_render_target
= grub_video_vbe_create_render_target
,
1628 .delete_render_target
= grub_video_vbe_delete_render_target
,
1629 .set_active_render_target
= grub_video_vbe_set_active_render_target
,
1630 .get_active_render_target
= grub_video_vbe_get_active_render_target
,
1635 GRUB_MOD_INIT(video_i386_pc_vbe
)
1637 grub_video_register (&grub_video_vbe_adapter
);
1640 GRUB_MOD_FINI(video_i386_pc_vbe
)
1642 grub_video_unregister (&grub_video_vbe_adapter
);