diff --git a/headers/private/graphics/vesa/vesa_info.h b/headers/private/graphics/vesa/vesa_info.h index 77d4fe6379..1a8b6d9b45 100644 --- a/headers/private/graphics/vesa/vesa_info.h +++ b/headers/private/graphics/vesa/vesa_info.h @@ -37,11 +37,6 @@ struct vesa_shared_info { display_mode current_mode; uint32 bytes_per_row; - area_id frame_buffer_area; // area of frame buffer - uint8* frame_buffer; - // pointer to frame buffer (visible by all apps!) - uint8* physical_frame_buffer; - uint32 vesa_mode_offset; uint32 vesa_mode_count; @@ -62,6 +57,7 @@ struct vesa_shared_info { // list ioctls enum { VESA_GET_PRIVATE_DATA = B_DEVICE_OP_CODES_END + 1, + VESA_CLONE_FRAME_BUFFER, VESA_GET_DEVICE_NAME, VESA_SET_DISPLAY_MODE, VESA_GET_DPMS_MODE, diff --git a/src/add-ons/accelerants/framebuffer/accelerant.cpp b/src/add-ons/accelerants/framebuffer/accelerant.cpp index 8b442c20e0..643f6e783f 100644 --- a/src/add-ons/accelerants/framebuffer/accelerant.cpp +++ b/src/add-ons/accelerants/framebuffer/accelerant.cpp @@ -50,6 +50,7 @@ init_common(int device, bool isClone) gInfo->is_clone = isClone; gInfo->device = device; gInfo->current_mode = UINT16_MAX; + gInfo->frame_buffer_area = -1; // get basic info from driver @@ -74,6 +75,7 @@ init_common(int device, bool isClone) static void uninit_common(void) { + delete_area(gInfo->frame_buffer_area); delete_area(gInfo->shared_info_area); gInfo->shared_info_area = -1; gInfo->shared_info = NULL; @@ -106,6 +108,16 @@ framebuffer_init_accelerant(int device) return status; } + area_info info; + status = ioctl(gInfo->device, VESA_CLONE_FRAME_BUFFER, &info, sizeof(info)); + if (status != B_OK) { + uninit_common(); + return status; + } + + gInfo->frame_buffer_area = info.area; + gInfo->frame_buffer = info.address; + return B_OK; } diff --git a/src/add-ons/accelerants/framebuffer/accelerant.h b/src/add-ons/accelerants/framebuffer/accelerant.h index ac5f035958..ed85f6a660 100644 --- a/src/add-ons/accelerants/framebuffer/accelerant.h +++ b/src/add-ons/accelerants/framebuffer/accelerant.h @@ -21,6 +21,10 @@ typedef struct accelerant_info { // cloned list of standard display modes display_mode *mode_list; uint16 current_mode; + + area_id frame_buffer_area; + // cloned framebuffer + void* frame_buffer; } accelerant_info; extern accelerant_info *gInfo; diff --git a/src/add-ons/accelerants/framebuffer/mode.cpp b/src/add-ons/accelerants/framebuffer/mode.cpp index 2e7a2b67f2..7f88fa5960 100644 --- a/src/add-ons/accelerants/framebuffer/mode.cpp +++ b/src/add-ons/accelerants/framebuffer/mode.cpp @@ -134,8 +134,8 @@ framebuffer_get_frame_buffer_config(frame_buffer_config* config) { TRACE(("framebuffer_get_frame_buffer_config()\n")); - config->frame_buffer = gInfo->shared_info->frame_buffer; - config->frame_buffer_dma = gInfo->shared_info->physical_frame_buffer; + config->frame_buffer = gInfo->frame_buffer; + config->frame_buffer_dma = NULL; config->bytes_per_row = gInfo->shared_info->bytes_per_row; return B_OK; diff --git a/src/add-ons/accelerants/vesa/accelerant.cpp b/src/add-ons/accelerants/vesa/accelerant.cpp index 93b225fae1..85f5f2dbd3 100644 --- a/src/add-ons/accelerants/vesa/accelerant.cpp +++ b/src/add-ons/accelerants/vesa/accelerant.cpp @@ -49,6 +49,7 @@ init_common(int device, bool isClone) gInfo->is_clone = isClone; gInfo->device = device; gInfo->current_mode = UINT16_MAX; + gInfo->frame_buffer_area = -1; // get basic info from driver @@ -110,6 +111,7 @@ vesa_init_accelerant(int device) // Initialize current mode completely from the mode list vesa_propose_display_mode(&gInfo->shared_info->current_mode, NULL, NULL); + return B_OK; } diff --git a/src/add-ons/accelerants/vesa/accelerant.h b/src/add-ons/accelerants/vesa/accelerant.h index c7f0d7cfa2..bd1364c342 100644 --- a/src/add-ons/accelerants/vesa/accelerant.h +++ b/src/add-ons/accelerants/vesa/accelerant.h @@ -22,6 +22,10 @@ typedef struct accelerant_info { int16 current_mode; // index in the mode_list, or -1 if using a custom mode vesa_mode *vesa_modes; + + area_id frame_buffer_area; + // cloned framebuffer + void* frame_buffer; } accelerant_info; extern accelerant_info *gInfo; diff --git a/src/add-ons/accelerants/vesa/mode.cpp b/src/add-ons/accelerants/vesa/mode.cpp index c80ae40151..a559b12b7b 100644 --- a/src/add-ons/accelerants/vesa/mode.cpp +++ b/src/add-ons/accelerants/vesa/mode.cpp @@ -231,8 +231,13 @@ vesa_set_display_mode(display_mode* _mode) if (gInfo->current_mode == i) return B_OK; status_t result = ioctl(gInfo->device, VESA_SET_DISPLAY_MODE, &i, sizeof(i)); - if (result == B_OK) + if (result == B_OK) { + delete_area(gInfo->frame_buffer_area); + gInfo->frame_buffer_area = -1; + gInfo->frame_buffer = NULL; + gInfo->current_mode = i; + } return result; } } @@ -241,6 +246,10 @@ vesa_set_display_mode(display_mode* _mode) status_t result = ioctl(gInfo->device, VESA_SET_CUSTOM_DISPLAY_MODE, &mode, sizeof(display_mode)); if (result == B_OK) { + delete_area(gInfo->frame_buffer_area); + gInfo->frame_buffer_area = -1; + gInfo->frame_buffer = NULL; + gInfo->current_mode = -1; } @@ -278,8 +287,20 @@ vesa_get_frame_buffer_config(frame_buffer_config* config) { TRACE(("vesa_get_frame_buffer_config()\n")); - config->frame_buffer = gInfo->shared_info->frame_buffer; - config->frame_buffer_dma = gInfo->shared_info->physical_frame_buffer; + if (gInfo->frame_buffer == NULL) { + // Clone the current framebuffer. + area_info info; + status_t status = ioctl(gInfo->device, VESA_CLONE_FRAME_BUFFER, + &info, sizeof(info)); + if (status != B_OK) + return status; + + gInfo->frame_buffer_area = info.area; + gInfo->frame_buffer = info.address; + } + + config->frame_buffer = gInfo->frame_buffer; + config->frame_buffer_dma = NULL; config->bytes_per_row = gInfo->shared_info->bytes_per_row; return B_OK; diff --git a/src/add-ons/kernel/drivers/graphics/framebuffer/device.cpp b/src/add-ons/kernel/drivers/graphics/framebuffer/device.cpp index 914f35c306..9d47657c01 100644 --- a/src/add-ons/kernel/drivers/graphics/framebuffer/device.cpp +++ b/src/add-ons/kernel/drivers/graphics/framebuffer/device.cpp @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -113,6 +114,18 @@ device_ioctl(void* cookie, uint32 msg, void* buffer, size_t bufferLength) return B_OK; + case VESA_CLONE_FRAME_BUFFER: + { + void* dummy; + area_id area = vm_clone_area(B_CURRENT_TEAM, "cloned framebuffer", + &dummy, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, 0, + info->frame_buffer_area, true); + if (area < 0) + return area; + + return _user_get_area_info(area, (area_info*)buffer); + } + // needed to share data between kernel and accelerant case VESA_GET_PRIVATE_DATA: return user_memcpy(buffer, &info->shared_area, sizeof(area_id)); diff --git a/src/add-ons/kernel/drivers/graphics/framebuffer/framebuffer.cpp b/src/add-ons/kernel/drivers/graphics/framebuffer/framebuffer.cpp index 0de9aa3669..ed16a9568b 100644 --- a/src/add-ons/kernel/drivers/graphics/framebuffer/framebuffer.cpp +++ b/src/add-ons/kernel/drivers/graphics/framebuffer/framebuffer.cpp @@ -49,7 +49,7 @@ get_color_space_for_depth(uint32 depth) static status_t remap_frame_buffer(framebuffer_info& info, addr_t physicalBase, uint32 width, - uint32 height, int8 depth, uint32 bytesPerRow, bool initializing) + uint32 height, int8 depth, uint32 bytesPerRow) { vesa_shared_info& sharedInfo = *info.shared_info; addr_t frameBuffer = info.frame_buffer; @@ -63,25 +63,19 @@ remap_frame_buffer(framebuffer_info& info, addr_t physicalBase, uint32 width, if (area < 0) return area; - if (initializing) { - // We need to manually update the kernel's frame buffer address, - // since this frame buffer remapping has not been issued by the - // app_server (which would otherwise take care of this) - frame_buffer_update(frameBuffer, width, height, depth, - bytesPerRow); - } + frame_buffer_update(frameBuffer, width, height, depth, + bytesPerRow); - delete_area(info.shared_info->frame_buffer_area); + vm_change_clones_to_null_areas(info.frame_buffer_area); + delete_area(info.frame_buffer_area); info.frame_buffer = frameBuffer; - sharedInfo.frame_buffer_area = area; + info.frame_buffer_area = area; // Turn on write combining for the area vm_set_area_memory_type(area, base, B_WRITE_COMBINING_MEMORY); // Update shared frame buffer information - sharedInfo.frame_buffer = (uint8*)frameBuffer; - sharedInfo.physical_frame_buffer = (uint8*)physicalBase; sharedInfo.bytes_per_row = bytesPerRow; return B_OK; @@ -112,11 +106,11 @@ framebuffer_init(framebuffer_info& info) memset(&sharedInfo, 0, sizeof(vesa_shared_info)); - sharedInfo.frame_buffer_area = bufferInfo->area; + info.frame_buffer_area = bufferInfo->area; remap_frame_buffer(info, bufferInfo->physical_frame_buffer, bufferInfo->width, bufferInfo->height, bufferInfo->depth, - bufferInfo->bytes_per_row, true); + bufferInfo->bytes_per_row); // Does not matter if this fails - the frame buffer was already mapped // before. @@ -142,6 +136,7 @@ framebuffer_uninit(framebuffer_info& info) { dprintf(DEVICE_NAME": framebuffer_uninit()\n"); - delete_area(info.shared_info->frame_buffer_area); + vm_change_clones_to_null_areas(info.frame_buffer_area); + delete_area(info.frame_buffer_area); delete_area(info.shared_area); } diff --git a/src/add-ons/kernel/drivers/graphics/framebuffer/framebuffer_private.h b/src/add-ons/kernel/drivers/graphics/framebuffer/framebuffer_private.h index 4b9177b7a6..0b4a4a5877 100644 --- a/src/add-ons/kernel/drivers/graphics/framebuffer/framebuffer_private.h +++ b/src/add-ons/kernel/drivers/graphics/framebuffer/framebuffer_private.h @@ -23,6 +23,7 @@ struct framebuffer_info { struct vesa_shared_info* shared_info; area_id shared_area; + area_id frame_buffer_area; addr_t frame_buffer; }; diff --git a/src/add-ons/kernel/drivers/graphics/vesa/device.cpp b/src/add-ons/kernel/drivers/graphics/vesa/device.cpp index cca94479d1..2456bba893 100644 --- a/src/add-ons/kernel/drivers/graphics/vesa/device.cpp +++ b/src/add-ons/kernel/drivers/graphics/vesa/device.cpp @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -113,6 +114,18 @@ device_ioctl(void* cookie, uint32 msg, void* buffer, size_t bufferLength) return B_OK; + case VESA_CLONE_FRAME_BUFFER: + { + void* dummy; + area_id area = vm_clone_area(B_CURRENT_TEAM, "cloned framebuffer", + &dummy, B_ANY_ADDRESS, B_READ_AREA | B_WRITE_AREA, 0, + info->frame_buffer_area, true); + if (area < 0) + return area; + + return _user_get_area_info(area, (area_info*)buffer); + } + // needed to share data between kernel and accelerant case VESA_GET_PRIVATE_DATA: return user_memcpy(buffer, &info->shared_area, sizeof(area_id)); @@ -215,7 +228,7 @@ device_ioctl(void* cookie, uint32 msg, void* buffer, size_t bufferLength) if (user_memcpy(&args, buffer, sizeof(args)) != B_OK) return B_BAD_ADDRESS; - return vga_planar_blit(info->shared_info, args.source, + return vga_planar_blit(info, args.source, args.source_bytes_per_row, args.left, args.top, args.right, args.bottom); } diff --git a/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp b/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp index 4bf314b345..64eaf38b73 100644 --- a/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp +++ b/src/add-ons/kernel/drivers/graphics/vesa/vesa.cpp @@ -316,23 +316,19 @@ remap_frame_buffer(vesa_info& info, addr_t physicalBase, uint32 width, if (remap) { area_id area = map_physical_memory("vesa frame buffer", base, - size, B_ANY_KERNEL_ADDRESS, B_READ_AREA | B_WRITE_AREA, + size, B_ANY_KERNEL_ADDRESS, B_KERNEL_READ_AREA | B_KERNEL_WRITE_AREA, (void**)&frameBuffer); if (area < 0) return area; - if (initializing) { - // We need to manually update the kernel's frame buffer address, - // since this frame buffer remapping has not been issued by the - // app_server (which would otherwise take care of this) - frame_buffer_update(frameBuffer, width, height, depth, - bytesPerRow); - } + frame_buffer_update(frameBuffer, width, height, depth, + bytesPerRow); - delete_area(info.shared_info->frame_buffer_area); + vm_change_clones_to_null_areas(info.frame_buffer_area); + delete_area(info.frame_buffer_area); info.frame_buffer = frameBuffer; - sharedInfo.frame_buffer_area = area; + info.frame_buffer_area = area; // Turn on write combining for the area vm_set_area_memory_type(area, base, B_WRITE_COMBINING_MEMORY); @@ -346,8 +342,6 @@ remap_frame_buffer(vesa_info& info, addr_t physicalBase, uint32 width, frameBuffer += physicalBase - info.physical_frame_buffer; // Update shared frame buffer information - sharedInfo.frame_buffer = (uint8*)frameBuffer; - sharedInfo.physical_frame_buffer = (uint8*)physicalBase; sharedInfo.bytes_per_row = bytesPerRow; return B_OK; @@ -400,7 +394,7 @@ vesa_init(vesa_info& info) memcpy((uint8*)&sharedInfo + sharedSize, modes, modesSize); } - sharedInfo.frame_buffer_area = bufferInfo->area; + info.frame_buffer_area = bufferInfo->area; remap_frame_buffer(info, bufferInfo->physical_frame_buffer, bufferInfo->width, bufferInfo->height, bufferInfo->depth, @@ -476,7 +470,8 @@ vesa_uninit(vesa_info& info) { dprintf(DEVICE_NAME": vesa_uninit()\n"); - delete_area(info.shared_info->frame_buffer_area); + vm_change_clones_to_null_areas(info.frame_buffer_area); + delete_area(info.frame_buffer_area); delete_area(info.shared_area); } diff --git a/src/add-ons/kernel/drivers/graphics/vesa/vesa_private.h b/src/add-ons/kernel/drivers/graphics/vesa/vesa_private.h index 86abfd2199..f0ce23d360 100644 --- a/src/add-ons/kernel/drivers/graphics/vesa/vesa_private.h +++ b/src/add-ons/kernel/drivers/graphics/vesa/vesa_private.h @@ -33,6 +33,7 @@ struct vesa_info { uint8 vbe_capabilities; uint8 bits_per_gun; + area_id frame_buffer_area; addr_t frame_buffer; addr_t physical_frame_buffer; size_t physical_frame_buffer_size; diff --git a/src/add-ons/kernel/drivers/graphics/vesa/vga.cpp b/src/add-ons/kernel/drivers/graphics/vesa/vga.cpp index 79bea56493..d811b156cb 100644 --- a/src/add-ons/kernel/drivers/graphics/vesa/vga.cpp +++ b/src/add-ons/kernel/drivers/graphics/vesa/vga.cpp @@ -7,6 +7,7 @@ #include "vga.h" #include "driver.h" +#include #include #include @@ -40,7 +41,7 @@ vga_set_indexed_colors(uint8 first, uint8 *colors, uint16 count) status_t -vga_planar_blit(vesa_shared_info *info, uint8 *src, int32 srcBPR, +vga_planar_blit(vesa_info *info, uint8 *src, int32 srcBPR, int32 left, int32 top, int32 right, int32 bottom) { // If we don't actually have an ISA bus, bail. @@ -48,11 +49,11 @@ vga_planar_blit(vesa_shared_info *info, uint8 *src, int32 srcBPR, return B_BAD_ADDRESS; // If we don't actually have a frame_buffer, bail. - if (info->frame_buffer == NULL) + if (info->frame_buffer == 0) return B_BAD_ADDRESS; - int32 dstBPR = info->bytes_per_row; - uint8 *dst = info->frame_buffer + top * dstBPR + left / 8; + int32 dstBPR = info->shared_info->bytes_per_row; + uint8 *dst = (uint8*)(info->frame_buffer + top * dstBPR + left / 8); // TODO: this is awfully slow... // TODO: assumes BGR order diff --git a/src/add-ons/kernel/drivers/graphics/vesa/vga.h b/src/add-ons/kernel/drivers/graphics/vesa/vga.h index 573c99f86b..1fcfba5d97 100644 --- a/src/add-ons/kernel/drivers/graphics/vesa/vga.h +++ b/src/add-ons/kernel/drivers/graphics/vesa/vga.h @@ -6,11 +6,12 @@ #define _VGA_H -#include +#include "vesa_private.h" status_t vga_set_indexed_colors(uint8 first, uint8 *colors, uint16 count); -status_t vga_planar_blit(vesa_shared_info *info, uint8 *src, int32 srcBPR, +status_t vga_planar_blit(vesa_info *info, uint8 *src, int32 srcBPR, int32 left, int32 top, int32 right, int32 bottom); + #endif /* _VGA_H */