[haiku-development] [PATCH 2/2] Remap vesa frame buffer only if necessary.
- From: Jan Klötzke <jan.kloetzke@xxxxxxxxxx>
- To: haiku-development@xxxxxxxxxxxxx
- Date: Sat, 31 May 2008 15:38:16 +0200
* Allocate frame buffer area for the biggest mode
* Fall back to old behaviour when different modes have different frame buffer
addresses
---
headers/private/graphics/vesa/vesa_info.h | 1 +
headers/private/kernel/frame_buffer_console.h | 2 +
src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp | 57 +++++++++++---------
src/system/boot/platform/bios_ia32/video.cpp | 55 ++++++++++++--------
src/system/kernel/debug/frame_buffer_console.cpp | 2 +
5 files changed, 68 insertions(+), 49 deletions(-)
diff --git a/headers/private/graphics/vesa/vesa_info.h
b/headers/private/graphics/vesa/vesa_info.h
index 1de16a6..ea60578 100644
--- a/headers/private/graphics/vesa/vesa_info.h
+++ b/headers/private/graphics/vesa/vesa_info.h
@@ -31,6 +31,7 @@ struct vesa_shared_info {
uint8 *frame_buffer;
// pointer to frame buffer (visible by all apps!)
uint8 *physical_frame_buffer;
+ uint32 mapping_size;
uint32 vesa_mode_offset;
uint32 vesa_mode_count;
diff --git a/headers/private/kernel/frame_buffer_console.h
b/headers/private/kernel/frame_buffer_console.h
index 4c80a4c..06801db 100644
--- a/headers/private/kernel/frame_buffer_console.h
+++ b/headers/private/kernel/frame_buffer_console.h
@@ -16,6 +16,8 @@ struct kernel_args;
struct frame_buffer_boot_info {
area_id area;
addr_t frame_buffer;
+ addr_t frame_buffer_phys;
+ int32 frame_buffer_size;
int32 width;
int32 height;
int32 depth;
diff --git a/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp
b/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp
index 31971c6..4526dbd 100644
--- a/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp
+++ b/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp
@@ -131,6 +131,8 @@ vesa_init(vesa_info &info)
sharedInfo.frame_buffer_area = bufferInfo->area;
sharedInfo.frame_buffer = (uint8 *)bufferInfo->frame_buffer;
+ sharedInfo.physical_frame_buffer = (uint8
*)bufferInfo->frame_buffer_phys;
+ sharedInfo.mapping_size = bufferInfo->frame_buffer_size;
sharedInfo.current_mode.virtual_width = bufferInfo->width;
sharedInfo.current_mode.virtual_height = bufferInfo->height;
@@ -138,11 +140,6 @@ vesa_init(vesa_info &info)
bufferInfo->depth);
sharedInfo.bytes_per_row = bufferInfo->bytes_per_row;
- physical_entry mapping;
- get_memory_map((void *)sharedInfo.frame_buffer, B_PAGE_SIZE,
- &mapping, 1);
- sharedInfo.physical_frame_buffer = (uint8 *)mapping.address;
-
dprintf(DEVICE_NAME ": vesa_init() completed successfully!\n");
return B_OK;
}
@@ -173,7 +170,9 @@ vesa_set_display_mode(vesa_info &info, unsigned int mode)
}
area_id newFBArea;
- frame_buffer_boot_info *bufferInfo;
+ uint32 newFBSize;
+ frame_buffer_boot_info *bufferInfo =
+ (frame_buffer_boot_info *)get_boot_item(FRAME_BUFFER_BOOT_INFO,
NULL);
struct vbe_mode_info modeInfo;
// Get mode information
@@ -190,33 +189,39 @@ vesa_set_display_mode(vesa_info &info, unsigned int mode)
goto error;
}
- // Map new frame buffer
- void *frameBuffer;
- newFBArea = map_physical_memory("vesa_fb",
- (void *)modeInfo.physical_base,
- modeInfo.bytes_per_row * modeInfo.height, B_ANY_KERNEL_ADDRESS,
- B_READ_AREA | B_WRITE_AREA, &frameBuffer);
- if (newFBArea < B_OK) {
- status = (status_t)newFBArea;
- goto error;
+ // Remap the frame buffer only if it's now at other address or if the
+ // mapping is too small
+ newFBSize = modeInfo.bytes_per_row * modeInfo.height;
+ if (info.shared_info->physical_frame_buffer != (uint8
*)modeInfo.physical_base
+ || info.shared_info->mapping_size < newFBSize) {
+
+ void *frameBuffer;
+ newFBArea = map_physical_memory("vesa_fb",
+ (void *)modeInfo.physical_base, newFBSize,
B_ANY_KERNEL_ADDRESS,
+ B_READ_AREA | B_WRITE_AREA, &frameBuffer);
+ if (newFBArea < B_OK) {
+ status = (status_t)newFBArea;
+ goto error;
+ }
+ delete_area(info.shared_info->frame_buffer_area);
+
+ // Update shared frame buffer information
+ info.shared_info->frame_buffer_area = newFBArea;
+ info.shared_info->frame_buffer = (uint8 *)frameBuffer;
+ info.shared_info->mapping_size = newFBSize;
+ info.shared_info->physical_frame_buffer = (uint8
*)modeInfo.physical_base;
+
+ // Update boot item as it's used in vesa_init()
+ bufferInfo->area = newFBArea;
+ bufferInfo->frame_buffer = (addr_t)frameBuffer;
}
- delete_area(info.shared_info->frame_buffer_area);
- // Update shared frame buffer information
- info.shared_info->frame_buffer_area = newFBArea;
- info.shared_info->frame_buffer = (uint8 *)frameBuffer;
- info.shared_info->physical_frame_buffer = (uint8
*)modeInfo.physical_base;
+ // Update necessary stuff
info.shared_info->bytes_per_row = modeInfo.bytes_per_row;
info.shared_info->current_mode.virtual_width = modeInfo.width;
info.shared_info->current_mode.virtual_height = modeInfo.height;
info.shared_info->current_mode.space = get_color_space_for_depth(
modeInfo.bits_per_pixel);
-
- // Update boot item as it's used in vesa_init()
- bufferInfo
- = (frame_buffer_boot_info
*)get_boot_item(FRAME_BUFFER_BOOT_INFO, NULL);
- bufferInfo->area = newFBArea;
- bufferInfo->frame_buffer = (addr_t)frameBuffer;
bufferInfo->width = modeInfo.width;
bufferInfo->height = modeInfo.height;
bufferInfo->depth = modeInfo.bits_per_pixel;
diff --git a/src/system/boot/platform/bios_ia32/video.cpp
b/src/system/boot/platform/bios_ia32/video.cpp
index 2309989..a0aebd7 100644
--- a/src/system/boot/platform/bios_ia32/video.cpp
+++ b/src/system/boot/platform/bios_ia32/video.cpp
@@ -364,6 +364,8 @@ vesa_init(vbe_info_block *info, video_mode **_standardMode)
// fill mode list and find standard video mode
video_mode *standardMode = NULL;
+ uint32 fbBase = 0;
+ uint32 fbSize = 0;
for (int32 i = 0; true; i++) {
uint16 mode = ((uint16 *)info->mode_list)[i];
@@ -408,6 +410,17 @@ vesa_init(vbe_info_block *info, video_mode **_standardMode)
videoMode->bits_per_pixel = 15;
}
+ if (fbBase == 0 || fbBase ==
modeInfo.physical_base) {
+ fbBase = modeInfo.physical_base;
+ uint32 size = modeInfo.bytes_per_row *
modeInfo.height;
+ if (size > fbSize)
+ fbSize = size;
+ } else {
+ // different frame buffer base ->
cannot map whole frame
+ // buffer in one area for all modes
+ fbBase = 0xFFFFFFFF;
+ }
+
add_video_mode(videoMode);
}
} else
@@ -437,6 +450,9 @@ vesa_init(vbe_info_block *info, video_mode **_standardMode)
return B_ERROR;
}
+ gKernelArgs.frame_buffer.physical_buffer.start = fbBase;
+ gKernelArgs.frame_buffer.physical_buffer.size = fbSize;
+
*_standardMode = standardMode;
return B_OK;
}
@@ -844,8 +860,8 @@ platform_switch_to_logo(void)
if ((platform_boot_options() & BOOT_OPTION_DEBUG_OUTPUT) != 0)
return;
- addr_t lastBase = gKernelArgs.frame_buffer.physical_buffer.start;
- size_t lastSize = gKernelArgs.frame_buffer.physical_buffer.size;
+ addr_t fbBase = gKernelArgs.frame_buffer.physical_buffer.start;
+ size_t fbSize = gKernelArgs.frame_buffer.physical_buffer.size;
if (sVesaCompatible && sMode != NULL) {
if (!sModeChosen)
@@ -866,9 +882,14 @@ platform_switch_to_logo(void)
gKernelArgs.frame_buffer.height = modeInfo.height;
gKernelArgs.frame_buffer.bytes_per_row = modeInfo.bytes_per_row;
gKernelArgs.frame_buffer.depth = modeInfo.bits_per_pixel;
- gKernelArgs.frame_buffer.physical_buffer.size =
modeInfo.bytes_per_row
- * gKernelArgs.frame_buffer.height;
- gKernelArgs.frame_buffer.physical_buffer.start =
modeInfo.physical_base;
+
+ uint32 size = modeInfo.bytes_per_row *
gKernelArgs.frame_buffer.height;
+ if (modeInfo.physical_base != fbBase) {
+ fbBase = modeInfo.physical_base;
+ fbSize = size;
+ } else if (size > fbSize) {
+ fbSize = size;
+ }
} else {
fallback:
// use standard VGA mode 640x480x4
@@ -878,32 +899,20 @@ fallback:
gKernelArgs.frame_buffer.height = 480;
gKernelArgs.frame_buffer.bytes_per_row = 640 / 2;
gKernelArgs.frame_buffer.depth = 4;
- gKernelArgs.frame_buffer.physical_buffer.size
- = gKernelArgs.frame_buffer.width
+ fbSize = gKernelArgs.frame_buffer.width
* gKernelArgs.frame_buffer.height / 2;
- gKernelArgs.frame_buffer.physical_buffer.start = 0xa0000;
+ fbBase = 0xa0000;
}
+ gKernelArgs.frame_buffer.physical_buffer.size = fbSize;
+ gKernelArgs.frame_buffer.physical_buffer.start = fbBase;
dprintf("video mode: %ux%ux%u\n", gKernelArgs.frame_buffer.width,
gKernelArgs.frame_buffer.height,
gKernelArgs.frame_buffer.depth);
gKernelArgs.frame_buffer.enabled = true;
- // If the new frame buffer is either larger than the old one or located
at
- // a different address, we need to remap it, so we first have to throw
- // away its previous mapping
- if (lastBase != 0
- && (lastBase != gKernelArgs.frame_buffer.physical_buffer.start
- || lastSize <
gKernelArgs.frame_buffer.physical_buffer.size)) {
- mmu_free((void *)sFrameBuffer, lastSize);
- lastBase = 0;
- }
- if (lastBase == 0) {
- // the graphics memory has not been mapped yet!
- sFrameBuffer = mmu_map_physical_memory(
- gKernelArgs.frame_buffer.physical_buffer.start,
- gKernelArgs.frame_buffer.physical_buffer.size,
kDefaultPageFlags);
- }
+ // map the graphics memory
+ sFrameBuffer = mmu_map_physical_memory(fbBase, fbSize,
kDefaultPageFlags);
// clear the video memory
memset((void *)sFrameBuffer, 0,
diff --git a/src/system/kernel/debug/frame_buffer_console.cpp
b/src/system/kernel/debug/frame_buffer_console.cpp
index c5b7b88..aedb71d 100644
--- a/src/system/kernel/debug/frame_buffer_console.cpp
+++ b/src/system/kernel/debug/frame_buffer_console.cpp
@@ -412,6 +412,8 @@ frame_buffer_console_init(kernel_args *args)
sBootInfo.area = sConsole.area;
sBootInfo.frame_buffer = (addr_t)frameBuffer;
+ sBootInfo.frame_buffer_phys = args->frame_buffer.physical_buffer.start;
+ sBootInfo.frame_buffer_size = args->frame_buffer.physical_buffer.size;
sBootInfo.width = args->frame_buffer.width;
sBootInfo.height = args->frame_buffer.height;
sBootInfo.depth = args->frame_buffer.depth;
--
1.5.4.2
- References:
- [haiku-development] [PATCH] Updated: VESA driver handling
- From: Jan Klötzke
Other related posts:
- » [haiku-development] [PATCH 2/2] Remap vesa frame buffer only if necessary.
- » [haiku-development] Re: [PATCH 2/2] Remap vesa frame buffer only if necessary.
- » [haiku-development] Re: [PATCH 2/2] Remap vesa frame buffer only if necessary.
- [haiku-development] [PATCH] Updated: VESA driver handling
- From: Jan Klötzke