diff --git a/headers/private/graphics/intel_extreme/intel_extreme.h b/headers/private/graphics/intel_extreme/intel_extreme.h index 6bf85a7963..5a71841d23 100644 --- a/headers/private/graphics/intel_extreme/intel_extreme.h +++ b/headers/private/graphics/intel_extreme/intel_extreme.h @@ -64,7 +64,6 @@ struct intel_shared_info { area_id registers_area; // area of memory mapped registers uint8 *physical_status_page; - area_id cursor_area; uint8 *physical_cursor_memory; area_id graphics_memory_area; uint8 *graphics_memory; @@ -83,6 +82,12 @@ struct intel_shared_info { sem_id vblank_sem; + uint32 cursor_buffer_offset; + uint32 cursor_format; + bool cursor_visible; + uint16 cursor_hot_x; + uint16 cursor_hot_y; + uint32 device_type; char device_identifier[32]; struct pll_info pll_info; @@ -97,7 +102,6 @@ struct intel_info { area_id registers_area; struct intel_shared_info *shared_info; area_id shared_area; - area_id cursor_area; struct overlay_registers *overlay_registers; // update buffer, shares an area with shared_info @@ -267,6 +271,8 @@ struct intel_free_graphics_memory { #define CURSOR_FORMAT_4_COLORS (2UL << 24) #define CURSOR_FORMAT_ARGB (4UL << 24) #define CURSOR_FORMAT_XRGB (5UL << 24) +#define CURSOR_POSITION_NEGATIVE 0x8000 +#define CURSOR_POSITION_MASK 0x3fff // ring buffer commands diff --git a/src/add-ons/accelerants/intel_extreme/Jamfile b/src/add-ons/accelerants/intel_extreme/Jamfile index 0f1d4e19df..304c018ac4 100644 --- a/src/add-ons/accelerants/intel_extreme/Jamfile +++ b/src/add-ons/accelerants/intel_extreme/Jamfile @@ -8,6 +8,7 @@ UsePrivateHeaders [ FDirName graphics common ] ; Addon intel_extreme.accelerant : accelerants : accelerant.cpp + cursor.cpp dpms.cpp engine.cpp hooks.cpp diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.cpp b/src/add-ons/accelerants/intel_extreme/accelerant.cpp index e4c82a48e1..3719a32af9 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.cpp +++ b/src/add-ons/accelerants/intel_extreme/accelerant.cpp @@ -128,19 +128,8 @@ init_common(int device, bool isClone) return status; } - AreaCloner cursorCloner; - gInfo->cursor_area = cursorCloner.Clone("intel extreme cursor", - (void **)&gInfo->cursor_memory, B_ANY_ADDRESS, - B_READ_AREA | B_WRITE_AREA, - gInfo->shared_info->cursor_area); - if (cursorCloner.InitCheck() < B_OK) { - // we can't do a hardware cursor then... - gInfo->cursor_memory = NULL; - } - sharedCloner.Keep(); regsCloner.Keep(); - cursorCloner.Keep(); // The overlay registers, hardware status, and cursor memory share // a single area with the shared_info @@ -159,7 +148,6 @@ init_common(int device, bool isClone) static void uninit_common(void) { - delete_area(gInfo->cursor_area); delete_area(gInfo->regs_area); delete_area(gInfo->shared_info_area); diff --git a/src/add-ons/accelerants/intel_extreme/accelerant.h b/src/add-ons/accelerants/intel_extreme/accelerant.h index dfb0afaf7c..86ce0a68a7 100644 --- a/src/add-ons/accelerants/intel_extreme/accelerant.h +++ b/src/add-ons/accelerants/intel_extreme/accelerant.h @@ -49,7 +49,6 @@ struct accelerant_info { hardware_status *status; uint8 *cursor_memory; - area_id cursor_area; int device; bool is_clone; diff --git a/src/add-ons/accelerants/intel_extreme/cursor.cpp b/src/add-ons/accelerants/intel_extreme/cursor.cpp new file mode 100644 index 0000000000..96d8cef2c5 --- /dev/null +++ b/src/add-ons/accelerants/intel_extreme/cursor.cpp @@ -0,0 +1,124 @@ +/* + * Copyright 2006, Haiku, Inc. All Rights Reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Axel Dörfler, axeld@pinc-software.de + */ + + +#include "accelerant_protos.h" +#include "accelerant.h" + +#include + + +status_t +intel_set_cursor_shape(uint16 width, uint16 height, uint16 hotX, uint16 hotY, + uint8 *andMask, uint8 *xorMask) +{ + if (width > 64 || height > 64) + return B_BAD_VALUE; + + write32(INTEL_CURSOR_CONTROL, 0); + // disable cursor + + // In two-color mode, the data is ordered as follows (always 64 bit per line): + // plane 1: line 0 (AND mask) + // plane 0: line 0 (XOR mask) + // plane 1: line 1 (AND mask) + // ... + // + // If the planes add to the value 0x2, the corresponding pixel is + // transparent, for 0x3 it inverts the background, so only the first + // two palette entries will be used (since we're using the 2 color mode). + + uint8 *data = gInfo->cursor_memory; + uint8 byteWidth = (width + 7) / 8; + + for (int32 y = 0; y < height; y++) { + for (int32 x = 0; x < byteWidth; x++) { + data[16 * y + x] = andMask[byteWidth * y + x]; + data[16 * y + x + 8] = xorMask[byteWidth * y + x]; + } + } + + // We can only change the width of the pixel, but apparently + // not the height (or at least I couldn't figure out how), + // so we need to make the rest transparent + for (uint32 y = height; y < 64; y++) { + for (int32 x = 0; x < byteWidth; x++) { + data[16 * y + x] = 0xff; + data[16 * y + x + 8] = 0; + } + } + + // set palette entries to white/black + write32(INTEL_CURSOR_PALETTE + 0, 0x00ffffff); + write32(INTEL_CURSOR_PALETTE + 4, 0); + + gInfo->shared_info->cursor_format = CURSOR_FORMAT_2_COLORS; + + write32(INTEL_CURSOR_CONTROL, CURSOR_ENABLED | gInfo->shared_info->cursor_format); + write32(INTEL_CURSOR_SIZE, width); + // TODO: I've no idea how to specify the height of the cursor - it seems to + // be always 64 pixels + + write32(INTEL_CURSOR_BASE, (uint32)gInfo->shared_info->physical_graphics_memory + + gInfo->shared_info->cursor_buffer_offset); + + // changing the hot point changes the cursor position, too + + if (hotX != gInfo->shared_info->cursor_hot_x + || hotY != gInfo->shared_info->cursor_hot_y) { + int32 x = read32(INTEL_CURSOR_POSITION); + int32 y = x >> 16; + x &= 0xffff; + + if (x & CURSOR_POSITION_NEGATIVE) + x = -(x & CURSOR_POSITION_MASK); + if (y & CURSOR_POSITION_NEGATIVE) + y = -(y & CURSOR_POSITION_MASK); + + x += gInfo->shared_info->cursor_hot_x; + y += gInfo->shared_info->cursor_hot_y; + + gInfo->shared_info->cursor_hot_x = hotX; + gInfo->shared_info->cursor_hot_y = hotY; + + intel_move_cursor(x, y); + } + + return B_OK; +} + + +void +intel_move_cursor(uint16 _x, uint16 _y) +{ + int32 x = (int32)_x - gInfo->shared_info->cursor_hot_x; + int32 y = (int32)_y - gInfo->shared_info->cursor_hot_x; + + if (x < 0) + x = -x | CURSOR_POSITION_NEGATIVE; + if (y < 0) + y = -y | CURSOR_POSITION_NEGATIVE; + + write32(INTEL_CURSOR_POSITION, (y << 16) | x); +} + + +void +intel_show_cursor(bool isVisible) +{ + if (gInfo->shared_info->cursor_visible == isVisible) + return; + + write32(INTEL_CURSOR_CONTROL, (isVisible ? CURSOR_ENABLED : 0) + | gInfo->shared_info->cursor_format); + write32(INTEL_CURSOR_BASE, (uint32)gInfo->shared_info->physical_graphics_memory + + gInfo->shared_info->cursor_buffer_offset); + + gInfo->shared_info->cursor_visible = isVisible; +} + diff --git a/src/add-ons/accelerants/intel_extreme/hooks.cpp b/src/add-ons/accelerants/intel_extreme/hooks.cpp index ae096657ce..9fa1090222 100644 --- a/src/add-ons/accelerants/intel_extreme/hooks.cpp +++ b/src/add-ons/accelerants/intel_extreme/hooks.cpp @@ -8,6 +8,7 @@ #include "accelerant_protos.h" +#include "accelerant.h" extern "C" void * @@ -61,13 +62,18 @@ get_accelerant_hook(uint32 feature, void *data) return intel_set_dpms_mode; /* cursor managment */ -/* case B_SET_CURSOR_SHAPE: - return intel_set_cursor_shape; + case B_SET_CURSOR_SHAPE: + if (gInfo->cursor_memory != NULL) + return intel_set_cursor_shape; case B_MOVE_CURSOR: - return intel_move_cursor; + if (gInfo->cursor_memory != NULL) + return intel_move_cursor; case B_SHOW_CURSOR: - return intel_show_cursor; -*/ + if (gInfo->cursor_memory != NULL) + return intel_show_cursor; + + return NULL; + /* engine/synchronization */ case B_ACCELERANT_ENGINE_COUNT: return intel_accelerant_engine_count; diff --git a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp index 45f882c033..33e008fbb3 100644 --- a/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp +++ b/src/add-ons/kernel/drivers/graphics/intel_extreme/intel_extreme.cpp @@ -438,25 +438,15 @@ intel_extreme_init(intel_info &info) // We also need to map the cursor memory into the GTT - // This could also be part of the usual graphics memory, but for some - // reason we need its physical address, too - and we only know that of - // the additional memory we allocated. - // Unfortunately, the GTT is not readable - we would need to compute - // the physical location of stolen memory with some heuristics (as it - // should be taken from the top of system memory), and hope that the - // BIOS adhered to this specification. + // This could also be part of the usual graphics memory, but since we + // need to make sure it's not in the graphics local memory (and I don't + // even know yet how to determine that a chip has local memory...), we + // keep the current strategy and put it into the shared area. + // Unfortunately, the GTT is not readable until it has been written into + // the double buffered register set; we cannot get its original contents. set_gtt_entry(info, totalSize, info.shared_info->physical_cursor_memory); - - AreaKeeper cursorMapper; - void *cursorMemory; - info.cursor_area = cursorMapper.Map("intel extreme cursor", - (void *)(info.shared_info->physical_graphics_memory + totalSize), - B_PAGE_SIZE, B_ANY_KERNEL_ADDRESS, 0, &cursorMemory); - if (cursorMapper.InitCheck() < B_OK) { - // we can't do a hardware cursor, then... - } - info.shared_info->cursor_area = info.cursor_area; + info.shared_info->cursor_buffer_offset = totalSize; init_interrupt_handler(info); @@ -488,7 +478,6 @@ intel_extreme_uninit(intel_info &info) delete_area(info.graphics_memory_area); delete_area(info.registers_area); delete_area(info.shared_area); - delete_area(info.cursor_area); // we may or may not have allocated additional graphics memory if (info.additional_memory_area >= B_OK)