* Implemented hardware cursor support.

* Turns out cursor handling is simpler as originally thought, so I could remove its
  physical mapping - it's still put into the shared area, though, although that isn't
  needed for this chip (but could eventually simplify the handling of other generations
  of this chip).


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@17450 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler 2006-05-14 13:41:33 +00:00
parent 8cb10e136c
commit 7d5957df85
7 changed files with 151 additions and 38 deletions

View File

@ -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

View File

@ -8,6 +8,7 @@ UsePrivateHeaders [ FDirName graphics common ] ;
Addon intel_extreme.accelerant : accelerants :
accelerant.cpp
cursor.cpp
dpms.cpp
engine.cpp
hooks.cpp

View File

@ -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);

View File

@ -49,7 +49,6 @@ struct accelerant_info {
hardware_status *status;
uint8 *cursor_memory;
area_id cursor_area;
int device;
bool is_clone;

View File

@ -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 <string.h>
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;
}

View File

@ -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;

View File

@ -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)