/* 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; // avoid compiler warning for unused arg 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; // avoid compiler warning for unused arg cmd |= gInfo.sharedInfo->commonCmd; while (count--) { int y = *pList++; int x = *pList++; int w = *pList++ - x + 1; // The MediaPlayer in Zeta 1.21 displays a window which has 2 zero width // spans which the Virge chips display as a line completely across the // screen; thus, the following if statement discards any span with zero // or negative width. if (w <= 0) continue; // Draw the span as a rectangle with a height of 1 to avoid the // extra complexity of drawing a line. 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; // use GXinvert for rop int cmd = DRAW | rop << 17 | CMD_RECT | CMD_XP | CMD_YP; (void)et; // avoid compiler warning for unused arg 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; // use GXcopy for rop int cmd = DRAW | rop << 17 | CMD_BITBLT | CMD_XP | CMD_YP; (void)et; // avoid compiler warning for unused arg 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; // restore these flags in case removed on last iteration 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 ++; } }