Haiku S3 Virge driver adapted from the X.org Virge driver.
Copyright (C) 1994-1999 The XFree86 Project, Inc. All Rights Reserved.
Copyright 2007 Haiku, Inc. All rights reserved.
Distributed under the terms of the MIT license.
Authors:
Gerald Zajac 2007
*/
#include "accel.h"
#include "virge.h"
static inline void WaitForSync()
{
while ((IN_SUBSYS_STAT() & 0x2000) == 0) ;
}
void
Virge_FillRectangle(engine_token* et, uint32 color, fill_rect_params* pList, uint32 count)
{
int rop = 0xF0;
int cmd = DRAW | rop << 17 | CMD_RECT | CMD_XP | CMD_YP ;
(void)et;
cmd |= gInfo.sharedInfo->commonCmd;
while (count--) {
int x = pList->left;
int y = pList->top;
int w = pList->right - x + 1;
int h = pList->bottom - y + 1;
gInfo.WaitQueue(4);
WriteReg32(PAT_FG_CLR, color);
WriteReg32(RWIDTH_HEIGHT, ((w - 1) << 16) | h);
WriteReg32(RDEST_XY, (x << 16) | y);
WriteReg32(CMD_SET, cmd);
WaitForSync();
pList++;
}
}
void
Virge_FillSpan(engine_token* et, uint32 color, uint16* pList, uint32 count)
{
int rop = 0xF0;
int cmd = DRAW | rop << 17 | CMD_RECT | CMD_XP | CMD_YP ;
(void)et;
cmd |= gInfo.sharedInfo->commonCmd;
while (count--) {
int y = *pList++;
int x = *pList++;
int w = *pList++ - x + 1;
if (w <= 0)
continue;
gInfo.WaitQueue(4);
WriteReg32(PAT_FG_CLR, color);
WriteReg32(RWIDTH_HEIGHT, ((w - 1) << 16) | 1);
WriteReg32(RDEST_XY, (x << 16) | y);
WriteReg32(CMD_SET, cmd);
WaitForSync();
}
}
void
Virge_InvertRectangle(engine_token* et, fill_rect_params* pList, uint32 count)
{
int rop = 0x55;
int cmd = DRAW | rop << 17 | CMD_RECT | CMD_XP | CMD_YP;
(void)et;
cmd |= gInfo.sharedInfo->commonCmd;
while (count--) {
int x = pList->left;
int y = pList->top;
int w = pList->right - x + 1;
int h = pList->bottom - y + 1;
gInfo.WaitQueue(3);
WriteReg32(RWIDTH_HEIGHT, ((w - 1) << 16) + h);
WriteReg32(RDEST_XY, (x << 16) | y);
WriteReg32(CMD_SET, cmd);
WaitForSync();
pList++;
}
}
void
Virge_ScreenToScreenBlit(engine_token* et, blit_params* pList, uint32 count)
{
int rop = 0xCC;
int cmd = DRAW | rop << 17 | CMD_BITBLT | CMD_XP | CMD_YP;
(void)et;
cmd |= gInfo.sharedInfo->commonCmd;
while (count--) {
int src_x = pList->src_left;
int src_y = pList->src_top;
int dest_x = pList->dest_left;
int dest_y = pList->dest_top;
int width = pList->width;
int height = pList->height;
if (src_x == dest_x && src_y == dest_y)
continue;
cmd |= CMD_XP | CMD_YP;
if (src_x < dest_x) {
src_x += width;
dest_x += width;
cmd &= ~CMD_XP;
}
if (src_y < dest_y) {
src_y += height;
dest_y += height;
cmd &= ~CMD_YP;
}
gInfo.WaitQueue(4);
WriteReg32(RWIDTH_HEIGHT, ((width) << 16) | (height + 1));
WriteReg32(RSRC_XY, (src_x << 16) | src_y);
WriteReg32(RDEST_XY, (dest_x << 16) | dest_y);
WriteReg32(CMD_SET, cmd);
WaitForSync();
pList ++;
}
}