From 5845b6ecc55d00e5f222d73646947f0187269a76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Tue, 27 Nov 2007 16:33:19 +0000 Subject: [PATCH] * The boot loader now remembers the bytes per row as told by the graphics card, and passes that information on to the kernel. This should fix wrong bytes per row with certain resolutions and graphics cards. * The boot loader now recognizes 15 bit modes that are advertised as 16 bit modes. This should fix wrong colors in 16 bit modes on some cards. * Reenabled setting MTRR for VESA mode - don't remember why I disabled it, but it works fine on my test machines. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23006 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- headers/private/kernel/boot/kernel_args.h | 9 +-- src/system/boot/platform/bios_ia32/video.cpp | 72 ++++++++++++------- .../kernel/debug/frame_buffer_console.cpp | 54 +++++++------- 3 files changed, 75 insertions(+), 60 deletions(-) diff --git a/headers/private/kernel/boot/kernel_args.h b/headers/private/kernel/boot/kernel_args.h index e636cf7c82..c6ce809e00 100644 --- a/headers/private/kernel/boot/kernel_args.h +++ b/headers/private/kernel/boot/kernel_args.h @@ -63,11 +63,12 @@ typedef struct kernel_args { struct driver_settings_file *driver_settings; struct { - bool enabled; - int32 width; - int32 height; - int32 depth; addr_range physical_buffer; + uint32 bytes_per_row; + uint16 width; + uint16 height; + uint8 depth; + bool enabled; } frame_buffer; void *debug_output; diff --git a/src/system/boot/platform/bios_ia32/video.cpp b/src/system/boot/platform/bios_ia32/video.cpp index fb749257b6..3d3789022f 100644 --- a/src/system/boot/platform/bios_ia32/video.cpp +++ b/src/system/boot/platform/bios_ia32/video.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2004-2006, Axel Dörfler, axeld@pinc-software.de. + * Copyright 2004-2007, Axel Dörfler, axeld@pinc-software.de. * Distributed under the terms of the MIT License. */ @@ -37,7 +37,8 @@ struct video_mode { list_link link; uint16 mode; - int32 width, height, bits_per_pixel; + uint16 width, height, bits_per_pixel; + uint32 bytes_per_row; }; static vbe_info_block sInfo; @@ -319,11 +320,11 @@ vesa_init(vbe_info_block *info, video_mode **_standardMode) if (mode == 0xffff) break; - TRACE((" %lx: ", mode)); + TRACE((" %x: ", mode)); struct vbe_mode_info modeInfo; if (vesa_get_mode_info(mode, &modeInfo) == B_OK) { - TRACE(("%ld x %ld x %ld (a = %ld, mem = %ld, phy = %lx, p = %ld, b = %ld)\n", + TRACE(("%u x %u x %u (a = %d, mem = %d, phy = %lx, p = %d, b = %d)\n", modeInfo.width, modeInfo.height, modeInfo.bits_per_pixel, modeInfo.attributes, modeInfo.memory_model, modeInfo.physical_base, modeInfo.num_planes, modeInfo.num_banks)); @@ -343,9 +344,16 @@ vesa_init(vbe_info_block *info, video_mode **_standardMode) continue; videoMode->mode = mode; + videoMode->bytes_per_row = modeInfo.bytes_per_row; videoMode->width = modeInfo.width; videoMode->height = modeInfo.height; videoMode->bits_per_pixel = modeInfo.bits_per_pixel; + if (modeInfo.bits_per_pixel == 16 + && modeInfo.red_mask_size + modeInfo.green_mask_size + + modeInfo.blue_mask_size == 15) { + // this is really a 15-bit mode + videoMode->bits_per_pixel = 15; + } if (standardMode == NULL) standardMode = videoMode; @@ -501,7 +509,8 @@ video_mode_menu() video_mode *mode = NULL; while ((mode = (video_mode *)list_get_next_item(&sModeList, mode)) != NULL) { char label[64]; - sprintf(label, "%ldx%ld %ld bit", mode->width, mode->height, mode->bits_per_pixel); + sprintf(label, "%ux%u %u bit", mode->width, mode->height, + mode->bits_per_pixel); menu->AddItem(item = new(nothrow) MenuItem(label)); item->SetData(mode); @@ -542,16 +551,19 @@ static void blit32(const uint8 *data, uint16 width, uint16 height, const uint8 *palette, uint16 left, uint16 top) { - uint32 *start = (uint32 *)sFrameBuffer + gKernelArgs.frame_buffer.width * top + left; + uint32 *start = (uint32 *)(sFrameBuffer + + gKernelArgs.frame_buffer.bytes_per_row * top + 4 * left); for (int32 y = 0; y < height; y++) { for (int32 x = 0; x < width; x++) { uint16 color = data[y * width + x] * 3; - start[x] = (palette[color + 0] << 16) | (palette[color + 1] << 8) | (palette[color + 2]); + start[x] = (palette[color + 0] << 16) | (palette[color + 1] << 8) + | (palette[color + 2]); } - start += gKernelArgs.frame_buffer.width; + start = (uint32 *)((addr_t)start + + gKernelArgs.frame_buffer.bytes_per_row); } } @@ -560,7 +572,8 @@ static void blit24(const uint8 *data, uint16 width, uint16 height, const uint8 *palette, uint16 left, uint16 top) { - uint8 *start = (uint8 *)sFrameBuffer + gKernelArgs.frame_buffer.width * 3 * top + 3 * left; + uint8 *start = (uint8 *)sFrameBuffer + + gKernelArgs.frame_buffer.bytes_per_row * top + 3 * left; for (int32 y = 0; y < height; y++) { for (int32 x = 0; x < width; x++) { @@ -572,7 +585,7 @@ blit24(const uint8 *data, uint16 width, uint16 height, start[index + 2] = palette[color + 0]; } - start += gKernelArgs.frame_buffer.width * 3; + start = start + gKernelArgs.frame_buffer.bytes_per_row; } } @@ -581,17 +594,20 @@ static void blit16(const uint8 *data, uint16 width, uint16 height, const uint8 *palette, uint16 left, uint16 top) { - uint16 *start = (uint16 *)sFrameBuffer + gKernelArgs.frame_buffer.width * top + left; + uint16 *start = (uint16 *)(sFrameBuffer + + gKernelArgs.frame_buffer.bytes_per_row * top + 2 * left); for (int32 y = 0; y < height; y++) { for (int32 x = 0; x < width; x++) { uint16 color = data[y * width + x] * 3; - start[x] = ((palette[color + 0] >> 3) << 11) | ((palette[color + 1] >> 2) << 5) + start[x] = ((palette[color + 0] >> 3) << 11) + | ((palette[color + 1] >> 2) << 5) | ((palette[color + 2] >> 3)); } - start += gKernelArgs.frame_buffer.width; + start = (uint16 *)((addr_t)start + + gKernelArgs.frame_buffer.bytes_per_row); } } @@ -600,17 +616,20 @@ static void blit15(const uint8 *data, uint16 width, uint16 height, const uint8 *palette, uint16 left, uint16 top) { - uint16 *start = (uint16 *)sFrameBuffer + gKernelArgs.frame_buffer.width * top + left; + uint16 *start = (uint16 *)(sFrameBuffer + + gKernelArgs.frame_buffer.bytes_per_row * top + 2 * left); for (int32 y = 0; y < height; y++) { for (int32 x = 0; x < width; x++) { uint16 color = data[y * width + x] * 3; - start[x] = ((palette[color + 0] >> 3) << 10) | ((palette[color + 1] >> 3) << 5) + start[x] = ((palette[color + 0] >> 3) << 10) + | ((palette[color + 1] >> 3) << 5) | ((palette[color + 2] >> 3)); } - start += gKernelArgs.frame_buffer.width; + start = (uint16 *)((addr_t)start + + gKernelArgs.frame_buffer.bytes_per_row); } } @@ -622,10 +641,11 @@ blit8(const uint8 *data, uint16 width, uint16 height, if (vesa_set_palette((const uint8 *)kPalette, 0, 256) != B_OK) dprintf("set palette failed!\n"); - addr_t start = sFrameBuffer + gKernelArgs.frame_buffer.width * top + left; + addr_t start = sFrameBuffer + gKernelArgs.frame_buffer.bytes_per_row * top + + left; for (int32 i = 0; i < height; i++) { - memcpy((void *)(start + gKernelArgs.frame_buffer.width * i), + memcpy((void *)(start + gKernelArgs.frame_buffer.bytes_per_row * i), &data[i * width], width); } } @@ -713,7 +733,6 @@ platform_switch_to_logo(void) addr_t lastBase = gKernelArgs.frame_buffer.physical_buffer.start; size_t lastSize = gKernelArgs.frame_buffer.physical_buffer.size; - int32 bytesPerPixel = 1; if (sVesaCompatible && sMode != NULL) { if (!sModeChosen) @@ -726,13 +745,12 @@ platform_switch_to_logo(void) if (vesa_get_mode_info(sMode->mode, &modeInfo) != B_OK) goto fallback; - bytesPerPixel = (modeInfo.bits_per_pixel + 7) / 8; - gKernelArgs.frame_buffer.width = modeInfo.width; 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 = gKernelArgs.frame_buffer.width - * gKernelArgs.frame_buffer.height * bytesPerPixel; + gKernelArgs.frame_buffer.physical_buffer.size = modeInfo.bytes_per_row + * gKernelArgs.frame_buffer.height; gKernelArgs.frame_buffer.physical_buffer.start = modeInfo.physical_base; } else { fallback: @@ -741,13 +759,14 @@ fallback: gKernelArgs.frame_buffer.width = 640; 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 * gKernelArgs.frame_buffer.height / 2; gKernelArgs.frame_buffer.physical_buffer.start = 0xa0000; } - gKernelArgs.frame_buffer.enabled = 1; + 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 @@ -760,8 +779,9 @@ fallback: } 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); + sFrameBuffer = mmu_map_physical_memory( + gKernelArgs.frame_buffer.physical_buffer.start, + gKernelArgs.frame_buffer.physical_buffer.size, kDefaultPageFlags); } // clear the video memory diff --git a/src/system/kernel/debug/frame_buffer_console.cpp b/src/system/kernel/debug/frame_buffer_console.cpp index 0283ebc93e..527d0c4e7b 100644 --- a/src/system/kernel/debug/frame_buffer_console.cpp +++ b/src/system/kernel/debug/frame_buffer_console.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2005-2006, Axel Dörfler, axeld@pinc-software.de. All rights reserved. + * Copyright 2005-2007, Axel Dörfler, axeld@pinc-software.de. All rights reserved. * Distributed under the terms of the MIT License. */ @@ -222,7 +222,8 @@ console_put_glyph(int32 x, int32 y, uint8 glyph, uint8 attr) static void -console_fill_glyph(int32 x, int32 y, int32 width, int32 height, uint8 glyph, uint8 attr) +console_fill_glyph(int32 x, int32 y, int32 width, int32 height, uint8 glyph, + uint8 attr) { if (x >= sConsole.columns || y >= sConsole.rows || !frame_buffer_console_available()) @@ -245,7 +246,8 @@ console_fill_glyph(int32 x, int32 y, int32 width, int32 height, uint8 glyph, uin static void -console_blit(int32 srcx, int32 srcy, int32 width, int32 height, int32 destx, int32 desty) +console_blit(int32 srcx, int32 srcy, int32 width, int32 height, int32 destx, + int32 desty) { if (!frame_buffer_console_available()) return; @@ -266,8 +268,10 @@ console_blit(int32 srcx, int32 srcy, int32 width, int32 height, int32 destx, int } for (int32 y = 0; y < height; y++) { - memmove((void *)(sConsole.frame_buffer + (desty + y) * sConsole.bytes_per_row + destx), - (void *)(sConsole.frame_buffer + (srcy + y) * sConsole.bytes_per_row + srcx), width); + memmove((void *)(sConsole.frame_buffer + (desty + y) + * sConsole.bytes_per_row + destx), + (void *)(sConsole.frame_buffer + (srcy + y) * sConsole.bytes_per_row + + srcx), width); } } @@ -281,7 +285,8 @@ console_clear(uint8 attr) switch (sConsole.bytes_per_pixel) { case 1: if (sConsole.depth >= 8) { - memset((void *)sConsole.frame_buffer, sPalette8[background_color(attr)], + memset((void *)sConsole.frame_buffer, + sPalette8[background_color(attr)], sConsole.height * sConsole.bytes_per_row); } else { // special case for VGA mode @@ -394,33 +399,22 @@ frame_buffer_console_init(kernel_args *args) if (sConsole.area < B_OK) return sConsole.area; - int32 bytesPerRow = args->frame_buffer.width; - switch (args->frame_buffer.depth) { - case 1: - case 4: - // special VGA mode (will always be treated as monochrome) - bytesPerRow /= 8; - break; - case 15: - case 16: - bytesPerRow *= 2; - break; - case 24: - bytesPerRow *= 3; - break; - case 32: - bytesPerRow *= 4; - break; + if (args->frame_buffer.depth == 4) { + // VGA mode will be treated as monochrome + args->frame_buffer.bytes_per_row /= 8; } - frame_buffer_update((addr_t)frameBuffer, args->frame_buffer.width, args->frame_buffer.height, - args->frame_buffer.depth, bytesPerRow); + + frame_buffer_update((addr_t)frameBuffer, args->frame_buffer.width, + args->frame_buffer.height, args->frame_buffer.depth, + args->frame_buffer.bytes_per_row); sBootInfo.frame_buffer = (addr_t)frameBuffer; sBootInfo.width = args->frame_buffer.width; sBootInfo.height = args->frame_buffer.height; sBootInfo.depth = args->frame_buffer.depth; - sBootInfo.bytes_per_row = bytesPerRow; - add_boot_item(FRAME_BUFFER_BOOT_INFO, &sBootInfo, sizeof(frame_buffer_boot_info)); + sBootInfo.bytes_per_row = args->frame_buffer.bytes_per_row; + add_boot_item(FRAME_BUFFER_BOOT_INFO, &sBootInfo, + sizeof(frame_buffer_boot_info)); return B_OK; } @@ -432,13 +426,13 @@ frame_buffer_console_init_post_modules(kernel_args *args) mutex_init(&sConsole.lock, "console_lock"); // TODO: enable MTRR in VESA mode! -// if (sConsole.frame_buffer == NULL) + if (sConsole.frame_buffer == NULL) return B_OK; // try to set frame buffer memory to write combined -// return vm_set_area_memory_type(sConsole.area, -// args->frame_buffer.physical_buffer.start, B_MTR_WC); + return vm_set_area_memory_type(sConsole.area, + args->frame_buffer.physical_buffer.start, B_MTR_WC); }